diff options
Diffstat (limited to 'main/src/addins/MonoDevelop.Refactoring')
99 files changed, 3142 insertions, 6076 deletions
diff --git a/main/src/addins/MonoDevelop.Refactoring/AssemblyInfo.cs b/main/src/addins/MonoDevelop.Refactoring/AssemblyInfo.cs index c787015813..120f59415c 100644 --- a/main/src/addins/MonoDevelop.Refactoring/AssemblyInfo.cs +++ b/main/src/addins/MonoDevelop.Refactoring/AssemblyInfo.cs @@ -7,3 +7,5 @@ using System.Reflection; [assembly: AssemblyDescription ("Provides refactoring support to MonoDevelop")] [assembly: AssemblyVersion ("2.6")] [assembly: AssemblyCopyright ("X11")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MonoDevelop.CSharpBinding")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MonoDevelop.PackageManagement")] diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs index 392aacd522..ecdfdee5d3 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisCommands.cs @@ -32,18 +32,15 @@ using MonoDevelop.Ide.Gui; using System.Collections.Generic; using Gtk; using MonoDevelop.AnalysisCore.Gui; -using MonoDevelop.SourceEditor; -using MonoDevelop.SourceEditor.QuickTasks; -using ICSharpCode.NRefactory.CSharp; using MonoDevelop.AnalysisCore.Fixes; using MonoDevelop.Ide; using MonoDevelop.CodeIssues; -using ICSharpCode.NRefactory.Refactoring; using MonoDevelop.CodeActions; using System.Threading; using System.IO; using MonoDevelop.Refactoring; using MonoDevelop.Ide.Gui.Dialogs; +using Microsoft.CodeAnalysis; namespace MonoDevelop.AnalysisCore { @@ -70,32 +67,32 @@ namespace MonoDevelop.AnalysisCore return; } var fixes = codeActionExtension.GetCurrentFixes (); - info.Enabled = fixes.Any (); + info.Enabled = !fixes.IsEmpty; } protected override void Run () { - var doc = MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument; - var view = doc.GetContent<MonoDevelop.SourceEditor.SourceEditorView> (); - if (view == null) { - LoggingService.LogWarning ("ShowFixesHandler could not find a SourceEditorView"); - return; - } - var widget = view.TextEditor; - var pt = view.DocumentToScreenLocation (doc.Editor.Caret.Location); - - var ces = new CommandEntrySet (); - ces.AddItem (AnalysisCommands.FixOperations); - var menu = MonoDevelop.Ide.IdeApp.CommandService.CreateMenu (ces); - - menu.Popup (null, null, delegate (Menu mn, out int x, out int y, out bool push_in) { - x = pt.X; - y = pt.Y; - push_in = true; - //if the menu would be off the bottom of the screen, "drop" it upwards - if (y + mn.Requisition.Height > widget.Screen.Height) - y -= mn.Requisition.Height + (int)widget.LineHeight; - }, 0, Global.CurrentEventTime); +// var doc = MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument; +// var view = doc.GetContent<MonoDevelop.SourceEditor.SourceEditorView> (); +// if (view == null) { +// LoggingService.LogWarning ("ShowFixesHandler could not find a SourceEditorView"); +// return; +// } +// var widget = view.TextEditor; +// var pt = view.DocumentToScreenLocation (doc.Editor.Caret.Location); +// +// var ces = new CommandEntrySet (); +// ces.AddItem (AnalysisCommands.FixOperations); +// var menu = MonoDevelop.Ide.IdeApp.CommandService.CreateMenu (ces); +// +// menu.Popup (null, null, delegate (Menu mn, out int x, out int y, out bool push_in) { +// x = pt.X; +// y = pt.Y; +// push_in = true; +// //if the menu would be off the bottom of the screen, "drop" it upwards +// if (y + mn.Requisition.Height > widget.Screen.Height) +// y -= mn.Requisition.Height + (int)widget.LineHeight; +// }, 0, Global.CurrentEventTime); } } @@ -103,11 +100,11 @@ namespace MonoDevelop.AnalysisCore { protected override void Update (CommandArrayInfo info) { - MonoDevelop.Ide.Gui.Document document; - IList<FixableResult> results; - if (!GetFixes (out document, out results)) - return; - PopulateInfos (info, document, results); +// MonoDevelop.Ide.Gui.Document document; +// IList<FixableResult> results; +// if (!GetFixes (out document, out results)) +// return; +// PopulateInfos (info, document, results); } protected override void Run (object dataItem) @@ -125,47 +122,47 @@ namespace MonoDevelop.AnalysisCore action.Fix (); return; } - var ca = dataItem as CodeAction; - if (ca != null) { - var doc = MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument; - - var context = doc.ParsedDocument.CreateRefactoringContext != null ? doc.ParsedDocument.CreateRefactoringContext (doc, default(CancellationToken)) : null; - using (var script = context.CreateScript ()) { - ca.Run (context, script); - } - return; - } - - - } - - public static bool GetFixes (out Document document, out IList<FixableResult> results) - { - results = null; - document = MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument; - if (document == null) - return false; - - var ext = document.GetContent<ResultsEditorExtension> (); - if (ext == null) - return false; - - var list = ext.GetResultsAtOffset (document.Editor.Caret.Offset).OfType<FixableResult> ().ToList (); - list.Sort (ResultCompareImportanceDesc); - results = list; +// var ca = dataItem as CodeAction; +// if (ca != null) { +// var doc = MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument; +// +// var context = doc.ParsedDocument.CreateRefactoringContext != null ? doc.ParsedDocument.CreateRefactoringContext (doc, default(CancellationToken)) : null; +// using (var script = context.CreateScript ()) { +// ca.Run (context, script); +// } +// return; +// } - if (results.Count > 0) - return true; - var codeActionExtension = document.GetContent <CodeActionEditorExtension> (); - if (codeActionExtension != null) { - var fixes = codeActionExtension.GetCurrentFixes (); - if (fixes != null) - return fixes.Any (CodeActionEditorExtension.IsAnalysisOrErrorFix); - } - return false; } +// public static bool GetFixes (out MonoDevelop.Ide.Gui.Document document, out IList<FixableResult> results) +// { +// results = null; +// document = MonoDevelop.Ide.IdeApp.Workbench.ActiveDocument; +// if (document == null) +// return false; +// +// var ext = document.GetContent<ResultsEditorExtension> (); +// if (ext == null) +// return false; +// +// var list = ext.GetResultsAtOffset (document.Editor.CaretOffset).OfType<FixableResult> ().ToList (); +// list.Sort (ResultCompareImportanceDesc); +// results = list; +// +// if (results.Count > 0) +// return true; +// +// var codeActionExtension = document.GetContent <CodeActionEditorExtension> (); +// if (codeActionExtension != null) { +// var fixes = codeActionExtension.GetCurrentFixes (); +// if (fixes != null) +// return !fixes.IsEmpty; +// } +// return false; +// } +// static int ResultCompareImportanceDesc (Result r1, Result r2) { int c = ((int)r1.Level).CompareTo ((int)r2.Level); @@ -174,113 +171,113 @@ namespace MonoDevelop.AnalysisCore return string.Compare (r1.Message, r2.Message, StringComparison.Ordinal); } - public static void PopulateInfos (CommandArrayInfo infos, Document doc, IEnumerable<FixableResult> results) - { - //FIXME: ellipsize long messages - int mnemonic = 1; - - var codeActionExtension = doc.GetContent <CodeActionEditorExtension> (); - var fixes = codeActionExtension.GetCurrentFixes (); - if (fixes != null) { - foreach (var _fix in fixes.Where (CodeActionEditorExtension.IsAnalysisOrErrorFix)) { - var fix = _fix; - if (fix is AnalysisContextActionProvider.AnalysisCodeAction) - continue; - var escapedLabel = fix.Title.Replace ("_", "__"); - var label = (mnemonic <= 10) - ? "_" + (mnemonic++ % 10).ToString () + " " + escapedLabel - : " " + escapedLabel; - infos.Add (label, fix); - } - } - - foreach (var result in results) { - bool firstAction = true; - foreach (var action in GetActions (doc, result)) { - if (firstAction) { - //FIXME: make this header item insensitive but not greyed out - infos.Add (new CommandInfo (result.Message.Replace ("_", "__"), false, false) { - Icon = GetIcon (result.Level) - }, null); - firstAction = false; - } - var escapedLabel = action.Label.Replace ("_", "__"); - var label = (mnemonic <= 10) - ? "_" + (mnemonic++ % 10).ToString () + " " + escapedLabel - : " " + escapedLabel; - infos.Add (label, action); - } - if (result.HasOptionsDialog) { - var declSet = new CommandInfoSet (); - declSet.Text = GettextCatalog.GetString ("_Options for \"{0}\"", result.OptionsTitle); - - bool hasBatchFix = false; - foreach (var fix in result.Fixes.OfType<IAnalysisFixAction> ().Where (f => f.SupportsBatchFix)) { - hasBatchFix = true; - var title = string.Format (GettextCatalog.GetString ("Apply in file: {0}"), fix.Label); - declSet.CommandInfos.Add (title, new System.Action(fix.BatchFix)); - } - if (hasBatchFix) - declSet.CommandInfos.AddSeparator (); - - var ir = result as InspectorResults; - if (ir != null) { - var inspector = ir.Inspector; - - if (inspector.CanSuppressWithAttribute) { - declSet.CommandInfos.Add (GettextCatalog.GetString ("_Suppress with attribute"), new System.Action(delegate { - inspector.SuppressWithAttribute (doc, ir.Region); - })); - } - - if (inspector.CanDisableWithPragma) { - declSet.CommandInfos.Add (GettextCatalog.GetString ("_Suppress with #pragma"), new System.Action(delegate { - inspector.DisableWithPragma (doc, ir.Region); - })); - } - - if (inspector.CanDisableOnce) { - declSet.CommandInfos.Add (GettextCatalog.GetString ("_Disable Once"), new System.Action(delegate { - inspector.DisableOnce (doc, ir.Region); - })); - } - - if (inspector.CanDisableAndRestore) { - declSet.CommandInfos.Add (GettextCatalog.GetString ("Disable _and Restore"), new System.Action(delegate { - inspector.DisableAndRestore (doc, ir.Region); - })); - } - } - - declSet.CommandInfos.Add (GettextCatalog.GetString ("_Configure Rule"), result); - - infos.Add (declSet); - } - } - } - - public static IEnumerable<IAnalysisFixAction> GetActions (Document doc, FixableResult result) - { - foreach (var fix in result.Fixes) - foreach (var handler in AnalysisExtensions.GetFixHandlers (fix.FixType)) - foreach (var action in handler.GetFixes (doc, fix)) - yield return action; - - } - - static string GetIcon (Severity severity) - { - switch (severity) { - case Severity.Error: - return Ide.Gui.Stock.Error; - case Severity.Warning: - return Ide.Gui.Stock.Warning; - case Severity.Hint: - return Ide.Gui.Stock.Information; - default: - return null; - } - } +// public static void PopulateInfos (CommandArrayInfo infos, MonoDevelop.Ide.Gui.Document doc, IEnumerable<FixableResult> results) +// { +//// //FIXME: ellipsize long messages +//// int mnemonic = 1; +//// +//// var codeActionExtension = doc.GetContent <CodeActionEditorExtension> (); +//// var fixes = codeActionExtension.GetCurrentFixes (); +//// if (fixes != null) { +//// foreach (var _fix in fixes.Where (CodeActionEditorExtension.IsAnalysisOrErrorFix)) { +//// var fix = _fix; +//// if (fix is AnalysisContextActionProvider.AnalysisCodeAction) +//// continue; +//// var escapedLabel = fix.Title.Replace ("_", "__"); +//// var label = (mnemonic <= 10) +//// ? "_" + (mnemonic++ % 10).ToString () + " " + escapedLabel +//// : " " + escapedLabel; +//// infos.Add (label, fix); +//// } +//// } +//// +//// foreach (var result in results) { +//// bool firstAction = true; +//// foreach (var action in GetActions (doc, result)) { +//// if (firstAction) { +//// //FIXME: make this header item insensitive but not greyed out +//// infos.Add (new CommandInfo (result.Message.Replace ("_", "__"), false, false) { +//// Icon = GetIcon (result.Level) +//// }, null); +//// firstAction = false; +//// } +//// var escapedLabel = action.Label.Replace ("_", "__"); +//// var label = (mnemonic <= 10) +//// ? "_" + (mnemonic++ % 10).ToString () + " " + escapedLabel +//// : " " + escapedLabel; +//// infos.Add (label, action); +//// } +//// if (result.HasOptionsDialog) { +//// var declSet = new CommandInfoSet (); +//// declSet.Text = GettextCatalog.GetString ("_Options for \"{0}\"", result.OptionsTitle); +//// +//// bool hasBatchFix = false; +//// foreach (var fix in result.Fixes.OfType<IAnalysisFixAction> ().Where (f => f.SupportsBatchFix)) { +//// hasBatchFix = true; +//// var title = string.Format (GettextCatalog.GetString ("Apply in file: {0}"), fix.Label); +//// declSet.CommandInfos.Add (title, new System.Action(fix.BatchFix)); +//// } +//// if (hasBatchFix) +//// declSet.CommandInfos.AddSeparator (); +//// +//// var ir = result as InspectorResults; +//// if (ir != null) { +//// var inspector = ir.Inspector; +//// +//// if (inspector.CanSuppressWithAttribute) { +//// declSet.CommandInfos.Add (GettextCatalog.GetString ("_Suppress with attribute"), new System.Action(delegate { +//// inspector.SuppressWithAttribute (doc, ir.Region); +//// })); +//// } +//// +//// if (inspector.CanDisableWithPragma) { +//// declSet.CommandInfos.Add (GettextCatalog.GetString ("_Suppress with #pragma"), new System.Action(delegate { +//// inspector.DisableWithPragma (doc, ir.Region); +//// })); +//// } +//// +//// if (inspector.CanDisableOnce) { +//// declSet.CommandInfos.Add (GettextCatalog.GetString ("_Disable Once"), new System.Action(delegate { +//// inspector.DisableOnce (doc, ir.Region); +//// })); +//// } +//// +//// if (inspector.CanDisableAndRestore) { +//// declSet.CommandInfos.Add (GettextCatalog.GetString ("Disable _and Restore"), new System.Action(delegate { +//// inspector.DisableAndRestore (doc, ir.Region); +//// })); +//// } +//// } +//// +//// declSet.CommandInfos.Add (GettextCatalog.GetString ("_Configure Rule"), result); +//// +//// infos.Add (declSet); +//// } +//// } +// } +// +// public static IEnumerable<IAnalysisFixAction> GetActions (MonoDevelop.Ide.Gui.Document doc, FixableResult result) +// { +// foreach (var fix in result.Fixes) +// foreach (var handler in AnalysisExtensions.GetFixHandlers (fix.FixType)) +// foreach (var action in handler.GetFixes (doc.Editor, doc, fix)) +// yield return action; +// +// } +// +// static string GetIcon (Severity severity) +// { +// switch (severity) { +// case Severity.Error: +// return Ide.Gui.Stock.Error; +// case Severity.Warning: +// return Ide.Gui.Stock.Warning; +// case Severity.Hint: +// return Ide.Gui.Stock.Information; +// default: +// return null; +// } +// } } class ExportRulesHandler : CommandHandler @@ -294,19 +291,19 @@ namespace MonoDevelop.AnalysisCore if (!dlg.Run ()) return; - Dictionary<BaseCodeIssueProvider, Severity> severities = new Dictionary<BaseCodeIssueProvider, Severity> (); + Dictionary<CodeDiagnosticDescriptor, DiagnosticSeverity?> severities = new Dictionary<CodeDiagnosticDescriptor, DiagnosticSeverity?> (); - foreach (var node in RefactoringService.GetInspectors (lang)) { - severities [node] = node.GetSeverity (); - if (node.HasSubIssues) { - foreach (var subIssue in node.SubIssues) { - severities [subIssue] = subIssue.GetSeverity (); - } - } + foreach (var node in BuiltInCodeDiagnosticProvider.GetBuiltInCodeDiagnosticDecsriptorsAsync (CodeRefactoringService.MimeTypeToLanguage(lang), true).Result) { + severities [node] = node.DiagnosticSeverity; +// if (node.GetProvider ().SupportedDiagnostics.Length > 1) { +// foreach (var subIssue in node.GetProvider ().SupportedDiagnostics) { +// severities [subIssue] = node.GetSeverity (subIssue); +// } +// } } - var grouped = severities.Keys.OfType<CodeIssueProvider> () - .GroupBy (node => node.Category) + var grouped = severities.Keys.OfType<CodeDiagnosticDescriptor> () + .GroupBy (node => node.GetProvider ().SupportedDiagnostics.First ().Category) .OrderBy (g => g.Key, StringComparer.Ordinal); using (var sw = new StreamWriter (dlg.SelectedFile)) { @@ -315,33 +312,31 @@ namespace MonoDevelop.AnalysisCore sw.WriteLine ("<h2>" + g.Key + "</h2>"); sw.WriteLine ("<table border='1'>"); - foreach (var node in g.OrderBy (n => n.Title, StringComparer.Ordinal)) { - var title = node.Title; - var desc = node.Description != title ? node.Description : ""; - sw.WriteLine ("<tr><td>" + title + "</td><td>" + desc + "</td><td>" + node.GetSeverity () + "</td></tr>"); - if (node.HasSubIssues) { - foreach (var subIssue in node.SubIssues) { - title = subIssue.Title; - desc = subIssue.Description != title ? subIssue.Description : ""; - sw.WriteLine ("<tr><td> - " + title + "</td><td>" + desc + "</td><td>" + subIssue.GetSeverity () + "</td></tr>"); + foreach (var node in g.OrderBy (n => n.Name, StringComparer.Ordinal)) { + var title = node.Name; + var desc = node.GetProvider ().SupportedDiagnostics.First ().Description.ToString () != title ? node.GetProvider ().SupportedDiagnostics.First ().Description : ""; + sw.WriteLine ("<tr><td>" + title + "</td><td>" + desc + "</td><td>" + node.DiagnosticSeverity + "</td></tr>"); + if (node.GetProvider ().SupportedDiagnostics.Length > 1) { + foreach (var subIssue in node.GetProvider ().SupportedDiagnostics) { + title = subIssue.Description.ToString (); + desc = subIssue.Description.ToString () != title ? subIssue.Description : ""; + sw.WriteLine ("<tr><td> - " + title + "</td><td>" + desc + "</td><td>" + node.GetSeverity (subIssue) + "</td></tr>"); } } } sw.WriteLine ("</table>"); } - Dictionary<CodeActionProvider, bool> providerStates = new Dictionary<CodeActionProvider, bool> (); - string disabledNodes = PropertyService.Get ("ContextActions." + lang, ""); - foreach (var node in RefactoringService.ContextAddinNodes.Where (n => n.MimeType == lang)) { - providerStates [node] = disabledNodes.IndexOf (node.IdString, StringComparison.Ordinal) < 0; + var providerStates = new Dictionary<CodeRefactoringDescriptor, bool> (); + foreach (var node in BuiltInCodeDiagnosticProvider.GetBuiltInCodeRefactoringDescriptorsAsync (CodeRefactoringService.MimeTypeToLanguage(lang), true).Result) { + providerStates [node] = node.IsEnabled; } sw.WriteLine ("<h1>Code Actions</h1>"); sw.WriteLine ("<table border='1'>"); - var sortedAndFiltered = providerStates.Keys.OrderBy (n => n.Title, StringComparer.Ordinal); + var sortedAndFiltered = providerStates.Keys.OrderBy (n => n.Name, StringComparer.Ordinal); foreach (var node in sortedAndFiltered) { - var desc = node.Title != node.Description ? node.Description : ""; - sw.WriteLine ("<tr><td>" + node.Title + "</td><td>" + desc + "</td></tr>"); + sw.WriteLine ("<tr><td>" + node.IdString + "</td><td>" + node.Name + "</td></tr>"); } sw.WriteLine ("</table>"); } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisOptions.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisOptions.cs index cedc34ccd3..97bd15dce7 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisOptions.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/AnalysisOptions.cs @@ -26,14 +26,15 @@ using System; using MonoDevelop.Core; -using MonoDevelop.SourceEditor.QuickTasks; namespace MonoDevelop.AnalysisCore { public static class AnalysisOptions { + public readonly static PropertyWrapper<bool> EnableFancyFeatures = new PropertyWrapper<bool> ("MonoDevelop.AnalysisCore.AnalysisEnabled", false); + public static PropertyWrapper<bool> AnalysisEnabled { - get { return QuickTaskStrip.EnableFancyFeatures; } + get { return EnableFancyFeatures; } } public readonly static PropertyWrapper<bool> EnableUnitTestEditorIntegration = new PropertyWrapper<bool> ("Testing.EnableUnitTestEditorIntegration", false); diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/FixableResult.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/FixableResult.cs index 7aaf76620f..ca3ca05b3e 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/FixableResult.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/FixableResult.cs @@ -26,26 +26,23 @@ using System; using System.Collections.Generic; -using MonoDevelop.SourceEditor; -using MonoDevelop.SourceEditor.QuickTasks; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.CSharp; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Refactoring; +using Microsoft.CodeAnalysis.Text; +using MonoDevelop.Ide.Editor; +using Microsoft.CodeAnalysis; namespace MonoDevelop.AnalysisCore { - public class FixableResult : Result - { - public FixableResult (DomRegion region, string message, Severity level, - IssueMarker mark, params IAnalysisFix[] fixes) - : base (region, message, level, mark) - { - this.Fixes = fixes; - } - - public IAnalysisFix[] Fixes { get; protected set; } - } +// public class FixableResult : Result +// { +// public FixableResult (TextSpan region, string message, DiagnosticSeverity level, +// IssueMarker mark, params IAnalysisFix[] fixes) +// : base (region, message, level, mark) +// { +// this.Fixes = fixes; +// } +// +// public IAnalysisFix[] Fixes { get; protected set; } +// } //FIXME: should this really use MonoDevelop.Ide.Gui.Document? Fixes could be more generic. public interface IAnalysisFix @@ -55,14 +52,14 @@ namespace MonoDevelop.AnalysisCore public interface IFixHandler { - IEnumerable<IAnalysisFixAction> GetFixes (MonoDevelop.Ide.Gui.Document doc, object fix); + IEnumerable<IAnalysisFixAction> GetFixes (TextEditor editor, DocumentContext doc, object fix); } public interface IAnalysisFixAction { string Label { get; } bool SupportsBatchFix { get; } - DocumentRegion DocumentRegion { get; } + TextSpan DocumentRegion { get; } string IdString { get; } void Fix (); void BatchFix (); diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/GenericFix.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/GenericFix.cs index 021445d57b..ca7bd317f0 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/GenericFix.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/GenericFix.cs @@ -25,63 +25,30 @@ // THE SOFTWARE. using System; using System.Collections.Generic; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.CSharp; using MonoDevelop.CodeIssues; using MonoDevelop.Ide; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Refactoring; +using Microsoft.CodeAnalysis.Text; +using MonoDevelop.Ide.Editor; +using Microsoft.CodeAnalysis; namespace MonoDevelop.AnalysisCore.Fixes { - public class InspectorResults : GenericResults - { - public BaseCodeIssueProvider Inspector { get; private set; } - - public InspectorResults (BaseCodeIssueProvider inspector, DomRegion region, string message, Severity level, IssueMarker mark, params GenericFix[] fixes) - : base (region, message, level, mark, fixes) - { - this.Inspector = inspector; - } - - public override bool HasOptionsDialog { get { return true; } } - public override string OptionsTitle { get { return GetTitle (Inspector); } } - public override void ShowResultOptionsDialog () - { - IdeApp.Workbench.ShowGlobalPreferencesDialog (null, "C#", dialog => { - var panel = dialog.GetPanel<CodeIssuePanel> ("C#"); - if (panel == null) - return; - panel.Widget.SelectCodeIssue (Inspector.IdString); - }); - } - - public static string GetTitle (BaseCodeIssueProvider inspector) - { - if (inspector.Parent == null) - return inspector.Title; - return inspector.Parent.Title + " -> " + inspector.Title; - } - - - } - - public class GenericResults : FixableResult - { - public GenericResults (DomRegion region, string message, Severity level, - IssueMarker mark, params GenericFix[] fixes) - : base (region, message, level, mark) - { - this.Fixes = fixes; - } - } +// public class GenericResults : FixableResult +// { +// public GenericResults (TextSpan region, string message, DiagnosticSeverity level, +// IssueMarker mark, params GenericFix[] fixes) +// : base (region, message, level, mark) +// { +// this.Fixes = fixes; +// } +// } public class GenericFix : IAnalysisFix, IAnalysisFixAction { Action fix; Action batchFix; string label; - public DocumentRegion DocumentRegion { get; set; } + public TextSpan DocumentRegion { get; set; } public string IdString { get; set; } public GenericFix (string label, Action fix, Action batchFix = null) @@ -130,7 +97,7 @@ namespace MonoDevelop.AnalysisCore.Fixes public class GenericFixHandler : IFixHandler { #region IFixHandler implementation - public IEnumerable<IAnalysisFixAction> GetFixes (MonoDevelop.Ide.Gui.Document doc, object fix) + public IEnumerable<IAnalysisFixAction> GetFixes (TextEditor editor, DocumentContext context, object fix) { yield return (GenericFix)fix; } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/RenameMemberFix.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/RenameMemberFix.cs index baa31de769..142643b508 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/RenameMemberFix.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Fixes/RenameMemberFix.cs @@ -27,13 +27,10 @@ using System; using System.Collections.Generic; using MonoDevelop.Core; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.Refactoring; using MonoDevelop.Refactoring.Rename; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.Semantics; -using Mono.TextEditor; +using Microsoft.CodeAnalysis.Text; +using MonoDevelop.Ide.Editor; namespace MonoDevelop.AnalysisCore.Fixes { @@ -42,14 +39,14 @@ namespace MonoDevelop.AnalysisCore.Fixes public string NewName { get; private set; } public string OldName { get; private set; } public string IdString { get; set; } - public IEntity Item { get; private set; } - - public RenameMemberFix (IEntity item, string oldName, string newName) - { - this.OldName = oldName; - this.NewName = newName; - this.Item = item; - } +// public IEntity Item { get; private set; } +// +// public RenameMemberFix (IEntity item, string oldName, string newName) +// { +// this.OldName = oldName; +// this.NewName = newName; +// this.Item = item; +// } public string FixType { get { return "RenameMember"; } } } @@ -58,23 +55,22 @@ namespace MonoDevelop.AnalysisCore.Fixes { //FIXME: why is this invalid on the parseddocuments loaded when the doc is first loaded? //maybe the item's type's SourceProject is null? - public IEnumerable<IAnalysisFixAction> GetFixes (MonoDevelop.Ide.Gui.Document doc, object fix) + public IEnumerable<IAnalysisFixAction> GetFixes (TextEditor editor, DocumentContext doc, object fix) { var renameFix = (RenameMemberFix)fix; var refactoring = new RenameRefactoring (); - var options = new RefactoringOptions (doc) { - SelectedItem = renameFix.Item, + var options = new RefactoringOptions (editor, doc) { + // SelectedItem = renameFix.Item, }; - if (renameFix.Item == null) { - ResolveResult resolveResult; - - options.SelectedItem = CurrentRefactoryOperationsHandler.GetItem (options.Document, out resolveResult); - } - - if (!refactoring.IsValid (options)) - yield break; - +// if (renameFix.Item == null) { +// ResolveResult resolveResult; +// options.SelectedItem = CurrentRefactoryOperationsHandler.GetItem (options.Editor, options.DocumentContext, out resolveResult); +// } +// +// if (!refactoring.IsValid (options)) +// yield break; +// var prop = new RenameRefactoring.RenameProperties () { NewName = renameFix.NewName, }; @@ -113,24 +109,24 @@ namespace MonoDevelop.AnalysisCore.Fixes public RenameRefactoring.RenameProperties Properties; public bool Preview; public string Label { get; set; } - public DocumentRegion DocumentRegion { get; set; } + public TextSpan DocumentRegion { get; set; } public string IdString { get; set; } public void Fix () { if (string.IsNullOrEmpty (Properties.NewName)) { - Refactoring.Run (Options); + //Refactoring.RunInplace (Options); return; } - //FIXME: performchanges should probably use a monitor too, as it can be slow - var changes = Refactoring.PerformChanges (Options, Properties); - if (Preview) { - MessageService.ShowCustomDialog (new RefactoringPreviewDialog (changes)); - } else { - var monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor ("Rename", null); - RefactoringService.AcceptChanges (monitor, changes); - } +// //FIXME: performchanges should probably use a monitor too, as it can be slow +// var changes = Refactoring.PerformChanges (Options, Properties); +// if (Preview) { +// MessageService.ShowCustomDialog (new RefactoringPreviewDialog (changes)); +// } else { +// var monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor ("Rename", null); +// RefactoringService.AcceptChanges (monitor, changes); +// } } public bool SupportsBatchFix { diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultMarker.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultMarker.cs index 332f0061cf..43ddf40ef4 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultMarker.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultMarker.cs @@ -24,15 +24,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using Mono.TextEditor; -using MonoDevelop.SourceEditor; -using MonoDevelop.SourceEditor.QuickTasks; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.Refactoring; using System.Collections.Generic; +using MonoDevelop.Core.Text; +using MonoDevelop.Ide.Editor; namespace MonoDevelop.AnalysisCore.Gui { +/* class ResultMarker : UnderlineTextSegmentMarker { readonly Result result; @@ -42,17 +40,9 @@ namespace MonoDevelop.AnalysisCore.Gui this.result = result; } - static bool IsOneLine (Result result) - { - return result.Region.BeginLine == result.Region.EndLine; - } - public Result Result { get { return result; } } //utility for debugging - public int Line { get { return result.Region.BeginLine; } } - public int ColStart { get { return IsOneLine (result)? (result.Region.BeginColumn) : 0; } } - public int ColEnd { get { return IsOneLine (result)? (result.Region.EndColumn) : 0; } } public string Message { get { return result.Message; } } static Cairo.Color GetColor (TextEditor editor, Result result) @@ -214,4 +204,5 @@ namespace MonoDevelop.AnalysisCore.Gui } #endregion } +*/ } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultTooltipProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultTooltipProvider.cs index e826f51f45..b5d18d54d1 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultTooltipProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultTooltipProvider.cs @@ -25,11 +25,10 @@ // THE SOFTWARE.
using System;
-using Mono.TextEditor;
-using MonoDevelop.SourceEditor;
using System.Text;
using System.Collections.Generic;
using MonoDevelop.Ide.TypeSystem;
+using MonoDevelop.Ide.Editor;
namespace MonoDevelop.AnalysisCore.Gui
{
@@ -39,57 +38,59 @@ namespace MonoDevelop.AnalysisCore.Gui {
}
- public override TooltipItem GetItem (TextEditor editor, int offset)
+ public override TooltipItem GetItem (TextEditor editor, DocumentContext ctx, int offset)
{
- //get the ResultsEditorExtension from the editor
- var ed = editor as ExtensibleTextEditor;
- if (ed == null)
- return null;
- var ext = ed.Extension;
- while (ext != null && !(ext is ResultsEditorExtension))
- ext = ext.Next;
- if (ext == null)
- return null;
- var resExt = (ResultsEditorExtension) ext;
-
- //get the results from the extension
- var results = resExt.GetResultsAtOffset (offset);
- if (results == null || results.Count == 0)
- return null;
-
- return new TooltipItem (results, editor.Document.GetLineByOffset (offset));
+// //get the ResultsEditorExtension from the editor
+// var ed = editor as ExtensibleTextEditor;
+// if (ed == null)
+// return null;
+// var ext = ed.Extension;
+// while (ext != null && !(ext is ResultsEditorExtension))
+// ext = ext.Next;
+// if (ext == null)
+// return null;
+// var resExt = (ResultsEditorExtension) ext;
+//
+// //get the results from the extension
+// var results = resExt.GetResultsAtOffset (offset);
+// if (results == null || results.Count == 0)
+// return null;
+//
+// return new TooltipItem (results, editor.GetLineByOffset (offset));
+ return null;
}
- protected override Gtk.Window CreateTooltipWindow (TextEditor editor, int offset, Gdk.ModifierType modifierState, TooltipItem item)
+ public override MonoDevelop.Components.Control CreateTooltipWindow (TextEditor editor, DocumentContext ctx, TooltipItem item, int offset, Gdk.ModifierType modifierState)
{
- //create a message string from all the results
- var results = (IList<Result>)item.Item;
- var sb = new StringBuilder ();
- bool first = false;
- foreach (var r in results) {
- if (!first)
- first = true;
- else
- sb.AppendLine ();
- sb.Append (r.Level.ToString ());
- sb.Append (": ");
- sb.Append (AmbienceService.EscapeText (r.Message));
- }
-
- //FIXME: use a nicer, more specialized tooltip window, with results formatting and hints about
- // commands and stuff
- var win = new LanguageItemWindow ((ExtensibleTextEditor) editor, modifierState, null, sb.ToString (), null);
- if (win.IsEmpty)
- return null;
- return win;
+// //create a message string from all the results
+// var results = (IList<Result>)item.Item;
+// var sb = new StringBuilder ();
+// bool first = false;
+// foreach (var r in results) {
+// if (!first)
+// first = true;
+// else
+// sb.AppendLine ();
+// sb.Append (r.Level.ToString ());
+// sb.Append (": ");
+// sb.Append (AmbienceService.EscapeText (r.Message));
+// }
+//
+// //FIXME: use a nicer, more specialized tooltip window, with results formatting and hints about
+// // commands and stuff
+// var win = new LanguageItemWindow ((ExtensibleTextEditor) editor, modifierState, null, sb.ToString (), null);
+// if (win.IsEmpty)
+// return null;
+// return win;
+ return null;
}
- protected override void GetRequiredPosition (TextEditor editor, Gtk.Window tipWindow, out int requiredWidth, out double xalign)
- {
- var win = (LanguageItemWindow) tipWindow;
- requiredWidth = win.SetMaxWidth (win.Screen.Width);
- xalign = 0.5;
- }
+// protected override void GetRequiredPosition (ITextEditor editor, Gtk.Window tipWindow, out int requiredWidth, out double xalign)
+// {
+// var win = (LanguageItemWindow) tipWindow;
+// requiredWidth = win.SetMaxWidth (win.Screen.Width);
+// xalign = 0.5;
+// }
}
}
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs index 4806feac47..0f9e33ae9d 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs @@ -30,20 +30,35 @@ using MonoDevelop.Ide.Gui.Content; using System.Threading; using System.Threading.Tasks; using System.IO; -using Mono.TextEditor; using System.Linq; -using MonoDevelop.SourceEditor.QuickTasks; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.Refactoring; +using MonoDevelop.Ide.Editor; +using MonoDevelop.Core.Text; +using MonoDevelop.Ide.Editor.Highlighting; +using MonoDevelop.Ide.Editor.Extension; +using Microsoft.CodeAnalysis; using MonoDevelop.CodeIssues; namespace MonoDevelop.AnalysisCore.Gui { + class AnalysisDocument + { + public TextEditor Editor { get; private set; } + public DocumentLocation CaretLocation { get; private set; } + public DocumentContext DocumentContext { get; private set; } + + public AnalysisDocument (TextEditor editor, DocumentContext documentContext) + { + this.Editor = editor; + this.CaretLocation = editor.CaretLocation; + this.DocumentContext = documentContext; + } + } + public class ResultsEditorExtension : TextEditorExtension, IQuickTaskProvider { bool disposed; - public override void Initialize () + protected override void Initialize () { base.Initialize (); @@ -61,12 +76,11 @@ namespace MonoDevelop.AnalysisCore.Gui if (disposed) return; enabled = false; - Document.DocumentParsed -= OnDocumentParsed; - CancelUpdateTimout (); + DocumentContext.DocumentParsed -= OnDocumentParsed; CancelTask (); AnalysisOptions.AnalysisEnabled.Changed -= AnalysisOptionsChanged; while (markers.Count > 0) - Document.Editor.Document.RemoveMarker (markers.Dequeue ()); + Editor.RemoveMarker (markers.Dequeue ()); tasks.Clear (); disposed = true; } @@ -90,20 +104,16 @@ namespace MonoDevelop.AnalysisCore.Gui if (enabled) return; enabled = true; - Document.DocumentParsed += OnDocumentParsed; - if (Document.ParsedDocument != null) + DocumentContext.DocumentParsed += OnDocumentParsed; + if (DocumentContext.ParsedDocument != null) OnDocumentParsed (null, null); } void CancelTask () { - if (src != null) { - src.Cancel (); - try { - oldTask.Wait (); - } catch (TaskCanceledException) { - } catch (AggregateException ex) { - ex.Handle (e => e is TaskCanceledException); + lock (updateLock) { + if (src != null) { + src.Cancel (); } } } @@ -113,7 +123,7 @@ namespace MonoDevelop.AnalysisCore.Gui if (!enabled) return; enabled = false; - Document.DocumentParsed -= OnDocumentParsed; + DocumentContext.DocumentParsed -= OnDocumentParsed; CancelTask (); new ResultsUpdater (this, new Result[0], CancellationToken.None).Update (); } @@ -125,21 +135,28 @@ namespace MonoDevelop.AnalysisCore.Gui void OnDocumentParsed (object sender, EventArgs args) { - if (!QuickTaskStrip.EnableFancyFeatures) + if (!AnalysisOptions.EnableFancyFeatures) return; CancelUpdateTimout (); - var doc = Document.ParsedDocument; + var doc = DocumentContext.ParsedDocument; if (doc == null) return; + var ad = new AnalysisDocument (Editor, DocumentContext); updateTimeout = GLib.Timeout.Add (250, delegate { lock (updateLock) { CancelTask (); src = new CancellationTokenSource (); var token = src.Token; oldTask = Task.Run (() => { - var result = CodeAnalysisRunner.Check (Document, doc, token); - var updater = new ResultsUpdater (this, result, token); - updater.Update (); + try { + var result = CodeDiagnosticRunner.Check (ad, token); + if (token.IsCancellationRequested) + return; + var updater = new ResultsUpdater (this, result, token); + updater.Update (); + } catch (OperationCanceledException) { + } catch (AggregateException) { + } }); updateTimeout = 0; return false; @@ -155,6 +172,7 @@ namespace MonoDevelop.AnalysisCore.Gui } } + class ResultsUpdater { readonly ResultsEditorExtension ext; @@ -178,12 +196,28 @@ namespace MonoDevelop.AnalysisCore.Gui public void Update () { - if (!QuickTaskStrip.EnableFancyFeatures || cancellationToken.IsCancellationRequested) + if (!AnalysisOptions.EnableFancyFeatures || cancellationToken.IsCancellationRequested) return; ext.tasks.Clear (); GLib.Idle.Add (IdleHandler); } - + + static Cairo.Color GetColor (TextEditor editor, Result result) + { + switch (result.Level) { + case DiagnosticSeverity.Hidden: + return DefaultSourceEditorOptions.Instance.GetColorStyle ().PlainText.Background; + case DiagnosticSeverity.Error: + return DefaultSourceEditorOptions.Instance.GetColorStyle ().UnderlineError.Color; + case DiagnosticSeverity.Warning: + return DefaultSourceEditorOptions.Instance.GetColorStyle ().UnderlineWarning.Color; + case DiagnosticSeverity.Info: + return DefaultSourceEditorOptions.Instance.GetColorStyle ().UnderlineSuggestion.Color; + default: + throw new System.ArgumentOutOfRangeException (); + } + } + //this runs as a glib idle handler so it can add/remove text editor markers //in order to to block the GUI thread, we batch them in UPDATE_COUNT bool IdleHandler () @@ -191,13 +225,13 @@ namespace MonoDevelop.AnalysisCore.Gui if (cancellationToken.IsCancellationRequested) return false; var editor = ext.Editor; - if (editor == null || editor.Document == null) + if (editor == null) return false; //clear the old results out at the same rate we add in the new ones for (int i = 0; oldMarkers > 0 && i < UPDATE_COUNT; i++) { if (cancellationToken.IsCancellationRequested) return false; - editor.Document.RemoveMarker (ext.markers.Dequeue ()); + editor.RemoveMarker (ext.markers.Dequeue ()); oldMarkers--; } //add in the new markers @@ -209,27 +243,30 @@ namespace MonoDevelop.AnalysisCore.Gui if (cancellationToken.IsCancellationRequested) return false; var currentResult = (Result)enumerator.Current; - if (currentResult.InspectionMark != IssueMarker.None) { - int start = editor.LocationToOffset (currentResult.Region.Begin); - int end = editor.LocationToOffset (currentResult.Region.End); + int start = currentResult.Region.Start; + int end = currentResult.Region.End; if (start >= end) continue; if (currentResult.InspectionMark == IssueMarker.GrayOut) { - var marker = new GrayOutMarker (currentResult, TextSegment.FromBounds (start, end)); + var marker = TextMarkerFactory.CreateGenericTextSegmentMarker (editor, TextSegmentMarkerEffect.GrayOut, TextSegment.FromBounds (start, end)); marker.IsVisible = currentResult.Underline; - editor.Document.AddMarker (marker); + marker.Tag = currentResult; + editor.AddMarker (marker); ext.markers.Enqueue (marker); - editor.Parent.TextViewMargin.RemoveCachedLine (editor.GetLineByOffset (start)); - editor.Parent.QueueDraw (); +// editor.Parent.TextViewMargin.RemoveCachedLine (editor.GetLineByOffset (start)); +// editor.Parent.QueueDraw (); } else { - var marker = new ResultMarker (currentResult, TextSegment.FromBounds (start, end)); + var effect = currentResult.InspectionMark == IssueMarker.DottedLine ? TextSegmentMarkerEffect.DottedLine : TextSegmentMarkerEffect.WavedLine; + var marker = TextMarkerFactory.CreateGenericTextSegmentMarker (editor, effect, TextSegment.FromBounds (start, end)); + marker.Color = GetColor (editor, currentResult); marker.IsVisible = currentResult.Underline; - editor.Document.AddMarker (marker); + marker.Tag = currentResult; + editor.AddMarker (marker); ext.markers.Enqueue (marker); } } - ext.tasks.Add (new QuickTask (currentResult.Message, currentResult.Region.Begin, currentResult.Level)); + ext.tasks.Add (new QuickTask (currentResult.Message, currentResult.Region.Start, currentResult.Level)); } return true; @@ -237,7 +274,7 @@ namespace MonoDevelop.AnalysisCore.Gui } //all markers known to be in the editor - Queue<ResultMarker> markers = new Queue<ResultMarker> (); + Queue<IGenericTextSegmentMarker> markers = new Queue<IGenericTextSegmentMarker> (); const int UPDATE_COUNT = 20; @@ -247,19 +284,19 @@ namespace MonoDevelop.AnalysisCore.Gui // var line = Editor.GetLineByOffset (offset); var list = new List<Result> (); - foreach (var marker in Editor.Document.GetTextSegmentMarkersAt (offset)) { + foreach (var marker in Editor.GetTextSegmentMarkersAt (offset)) { if (token.IsCancellationRequested) break; - var resultMarker = marker as ResultMarker; - if (resultMarker != null) - list.Add (resultMarker.Result); + var resultMarker = marker as IGenericTextSegmentMarker; + if (resultMarker != null && resultMarker.Tag is Result) + list.Add (resultMarker.Tag as Result); } return list; } public IEnumerable<Result> GetResults () { - return markers.Select (m => m.Result); + return markers.Select (m => m.Tag).OfType<Result> (); } #region IQuickTaskProvider implementation diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ICodeIssueProviderSource.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/IssueMarker.cs index 39ddd1a037..8713caf62d 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ICodeIssueProviderSource.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/IssueMarker.cs @@ -1,21 +1,21 @@ -// -// ICodeIssueProviderSource.cs -// +// +// IssueMarker.cs +// // Author: // Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) -// +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,23 +23,33 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System.Collections.Generic; -using System.Threading; -using MonoDevelop.Ide.TypeSystem; -using MonoDevelop.Projects; -using Mono.TextEditor; +using System; -namespace MonoDevelop.CodeIssues +namespace MonoDevelop.AnalysisCore { /// <summary> - /// A code issue provider source provides a way for language backends to add a set of generated code issue providers. + /// The issue marker is used to set how an issue should be marked inside the text editor. /// </summary> - public interface ICodeIssueProviderSource + public enum IssueMarker { /// <summary> - /// Gets the providers. + /// The issue is not shown inside the text editor. (But in the task bar) /// </summary> - IEnumerable<CodeIssueProvider> GetProviders (); - } -} + None, + + /// <summary> + /// The region is marked as underline in the severity color. + /// </summary> + WavedLine, + + /// <summary> + /// The region is marked as dotted line in the severity color. + /// </summary> + DottedLine, + /// <summary> + /// The text is grayed out. + /// </summary> + GrayOut + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs index 0e89e12711..7ed4a24101 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Result.cs @@ -25,25 +25,22 @@ // THE SOFTWARE. using System; -using ICSharpCode.NRefactory.Refactoring; using MonoDevelop.AnalysisCore.Extensions; -using MonoDevelop.SourceEditor; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.SourceEditor.QuickTasks; -using ICSharpCode.NRefactory.CSharp; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis; namespace MonoDevelop.AnalysisCore { public class Result { - public Result (DomRegion region, string message, bool underLine = true) + public Result (TextSpan region, string message, bool underLine = true) { this.Region = region; this.Message = message; this.Underline = underLine; } - public Result (DomRegion region, string message, Severity level, IssueMarker inspectionMark, bool underline = true) + public Result (TextSpan region, string message, DiagnosticSeverity level, IssueMarker inspectionMark, bool underline = true) { this.Region = region; this.Message = message; @@ -52,7 +49,7 @@ namespace MonoDevelop.AnalysisCore this.Underline = underline; } - public void SetSeverity (Severity level, IssueMarker inspectionMark) + public void SetSeverity (DiagnosticSeverity level, IssueMarker inspectionMark) { this.Level = level; this.InspectionMark = inspectionMark; @@ -66,9 +63,9 @@ namespace MonoDevelop.AnalysisCore } public string Message { get; private set; } - public Severity Level { get; private set; } + public DiagnosticSeverity Level { get; private set; } public IssueMarker InspectionMark { get; private set; } - public DomRegion Region { get; private set; } + public TextSpan Region { get; private set; } public bool Underline { get; private set; } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Rules/Adaptors.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Rules/Adaptors.cs deleted file mode 100644 index eaf8c6a3af..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Rules/Adaptors.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Adaptors.cs -// -// Author: -// Michael Hutchinson <mhutchinson@novell.com> -// -// Copyright (c) 2010 Novell, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; -using MonoDevelop.AnalysisCore.Fixes; -using MonoDevelop.Ide.Gui; -using ICSharpCode.NRefactory.TypeSystem; - -namespace MonoDevelop.AnalysisCore.Rules -{ - public static class Adapters - { - public static IUnresolvedFile GetCompilationUnit (Document input) - { - return input.ParsedDocument.ParsedFile; - } - } -}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/AnalysisCodeAction.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/AnalysisCodeAction.cs deleted file mode 100644 index 5641aecb60..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/AnalysisCodeAction.cs +++ /dev/null @@ -1,116 +0,0 @@ -// -// AnalysisQuickFix.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using MonoDevelop.AnalysisCore; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory; -using System.Threading; -using MonoDevelop.Ide; -using MonoDevelop.CodeIssues; -using MonoDevelop.AnalysisCore.Fixes; -using Mono.TextEditor; -using MonoDevelop.Ide.TypeSystem; - -namespace MonoDevelop.CodeActions -{ - class AnalysisContextActionProvider : CodeActionProvider - { - public Result Result { - get; - private set; - } - - public IAnalysisFixAction Action { - get; - private set; - } - - public AnalysisContextActionProvider (Result result, IAnalysisFixAction action) - { - Result = result; - Action = action; - Description = result.Message; - } - - public override System.Collections.Generic.IEnumerable<CodeAction> GetActions (MonoDevelop.Ide.Gui.Document document, object refactoringContext, TextLocation loc, CancellationToken cancellationToken) - { - yield return new AnalysisCodeAction (Action, Result) { - DocumentRegion = Action.DocumentRegion - }; - } - - internal class AnalysisCodeAction : CodeAction - { - public IAnalysisFixAction Action { - get; - private set; - } - public Result Result { - get; - private set; - } - - public AnalysisCodeAction (IAnalysisFixAction action, Result result) - { - Action = action; - Title = action.Label; - Result = result; - IdString = action.IdString; - } - - public override void Run (IRefactoringContext context, object script) - { - Action.Fix (); - } - - public override bool SupportsBatchRunning { - get { - return Action.SupportsBatchFix; - } - } - - public override void BatchRun (MonoDevelop.Ide.Gui.Document document, TextLocation loc) - { - Action.BatchFix (); - } - - public void ShowOptions (object sender, EventArgs e) - { - var inspectorResults = Result as InspectorResults; - if (inspectorResults != null) - inspectorResults.ShowResultOptionsDialog (); - } - - public void HideCodeIssue (object sender, EventArgs e) - { - var inspectorResults = Result as InspectorResults; - if (inspectorResults != null) - inspectorResults.Inspector.SetIsEnabled (false); - } - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeAction.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeAction.cs deleted file mode 100644 index 0aef83200c..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeAction.cs +++ /dev/null @@ -1,117 +0,0 @@ -// -// Result.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using ICSharpCode.NRefactory; -using System; -using Mono.TextEditor; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.NRefactory.Refactoring; -using MonoDevelop.Ide.TypeSystem; - -namespace MonoDevelop.CodeActions -{ - /// <summary> - /// A code action represents a menu entry that does edit operation in one document. - /// </summary> - public abstract class CodeAction - { - /// <summary> - /// Gets or sets the menu item text. - /// </summary> - public string Title { get; set; } - - /// <summary> - /// Gets or sets the id string. The id is used to identify a specific code action. - /// </summary> - public string IdString { get; set; } - - /// <summary> - /// The region of the code action. - /// </summary> - public DocumentRegion DocumentRegion { get; set; } - - /// <summary> - /// Gets or sets the type of the inspector that is the source of this action. - /// </summary> - /// <value>The type of the inspector.</value> - public Type InspectorType { get; set; } - - /// <summary> - /// Gets or sets the sibling key. - /// </summary> - /// <value>The sibling key.</value> - public object SiblingKey { get; set; } - - /// <summary> - /// Gets or sets the severity of the code action. - /// </summary> - /// <value>The severity.</value> - public Severity Severity { get; set; } - - protected CodeAction () - { - IdString = GetType ().FullName; - } - - /// <summary> - /// Performs the specified code action in document at loc. - /// </summary> - public abstract void Run (IRefactoringContext context, object script); - - /// <summary> - /// True if <see cref="BatchRun"/> can be used on the current instance. - /// </summary> - /// <value><c>true</c> if supports batch running; otherwise, <c>false</c>.</value> - public virtual bool SupportsBatchRunning { - get{ - return false; - } - } - - public virtual void BatchRun (MonoDevelop.Ide.Gui.Document document, TextLocation loc) - { - if (!SupportsBatchRunning) { - throw new InvalidOperationException ("Batch running is not supported."); - } - } - } - - public class DefaultCodeAction : CodeAction - { - public Action<RefactoringContext, Script> act; - - public DefaultCodeAction (string title, Action<RefactoringContext, Script> act) - { - Title = title; - this.act = act; - } - - public override void Run (IRefactoringContext context, object script) - { - act ((RefactoringContext)context, (Script)script); - } - } - -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionAddinNode.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionAddinNode.cs deleted file mode 100644 index 11b7701fbd..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionAddinNode.cs +++ /dev/null @@ -1,75 +0,0 @@ -// -// ContextActionCodon.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using Mono.Addins; - -namespace MonoDevelop.CodeActions -{ - public class CodeActionAddinNode : TypeExtensionNode - { - [NodeAttribute ("mimeType", Required=true, Description="The mime type of this action.")] - string mimeType = null; - - public string MimeType { - get { - return mimeType; - } - } - - [NodeAttribute ("_title", Required=true, Localizable=true, Description="The title of this action.")] - string title = null; - - public string Title { - get { - return title; - } - } - - [NodeAttribute ("_description", Required=true, Localizable=true, Description="The description of this action.")] - string description = null; - - public string Description { - get { - return description; - } - } - - CodeActionProvider action; - public CodeActionProvider Action { - get { - if (action == null) { - action = (CodeActionProvider)CreateInstance (); - action.Title = title; - action.Description = description; - action.MimeType = MimeType; - } - - return action; - } - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionContainer.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionContainer.cs new file mode 100644 index 0000000000..bf2ce53f55 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionContainer.cs @@ -0,0 +1,119 @@ +// +// CodeActionContainer.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CodeActions; +using System; +using MonoDevelop.CodeIssues; +using System.Linq; +using Microsoft.CodeAnalysis; +using System.Collections; + +namespace MonoDevelop.CodeActions +{ + class CodeActionContainer + { + public static readonly CodeActionContainer Empty = new CodeActionContainer(); + + public bool IsEmpty { + get { + return CodeFixActions.Count + CodeRefactoringActions.Count == 0; + } + } + + IReadOnlyList<ValidCodeDiagnosticAction> codeFixActions; + public IReadOnlyList<ValidCodeDiagnosticAction> CodeFixActions { + get { + return codeFixActions ?? new ValidCodeDiagnosticAction[0]; + } + private set { + codeFixActions = value; + } + } + + IReadOnlyList<ValidCodeAction> codeRefactoringActions; + + public IReadOnlyList<ValidCodeAction> CodeRefactoringActions { + get { + return codeRefactoringActions ?? new ValidCodeAction[0]; + } + private set { + codeRefactoringActions = value; + } + } + + public IEnumerable<ValidCodeAction> AllValidCodeActions { + get { + return CodeRefactoringActions.Concat (CodeFixActions); + } + } + + IReadOnlyList<Diagnostic> diagnosticsAtCaret; + public IReadOnlyList<Diagnostic> DiagnosticsAtCaret { + get { + return diagnosticsAtCaret ?? new Diagnostic[0]; + } + private set { + diagnosticsAtCaret = value.Distinct (new DiagnosticComparer()).ToList (); + } + } + + class DiagnosticComparer : IEqualityComparer<Diagnostic> + { + bool IEqualityComparer<Diagnostic>.Equals (Diagnostic x, Diagnostic y) + { + if (x.Id != null && y.Id != null) + return x.Id == y.Id; + return x.Equals (y); + } + + int IEqualityComparer<Diagnostic>.GetHashCode (Diagnostic obj) + { + return obj.Id != null ? obj.Id.GetHashCode () : obj.GetHashCode (); + } + } + + CodeActionContainer () + { + CodeFixActions = new List<ValidCodeDiagnosticAction> (); + CodeRefactoringActions = new List<ValidCodeAction> (); + DiagnosticsAtCaret = new List<Diagnostic> (); + } + + internal CodeActionContainer (List<ValidCodeDiagnosticAction> codeDiagnosticActions, List<ValidCodeAction> codeRefactoringActions, List<Diagnostic> diagnosticsAtCaret) + { + if (codeDiagnosticActions == null) + throw new ArgumentNullException ("codeDiagnosticActions"); + if (codeRefactoringActions == null) + throw new ArgumentNullException ("codeRefactoringActions"); + if (diagnosticsAtCaret == null) + throw new ArgumentNullException ("diagnosticsAtCaret"); + CodeFixActions = codeDiagnosticActions; + CodeRefactoringActions = codeRefactoringActions; + DiagnosticsAtCaret = diagnosticsAtCaret; + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs index 8cbdfbf6dc..b2077a0d16 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionEditorExtension.cs @@ -24,26 +24,32 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; -using MonoDevelop.Ide.Gui.Content; using Gtk; -using Mono.TextEditor; using System.Collections.Generic; using MonoDevelop.Components.Commands; -using MonoDevelop.SourceEditor.QuickTasks; using System.Linq; using MonoDevelop.Refactoring; -using ICSharpCode.NRefactory; using System.Threading; using MonoDevelop.Core; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.Semantics; -using MonoDevelop.AnalysisCore.Fixes; -using ICSharpCode.NRefactory.Refactoring; -using MonoDevelop.Ide.Gui; +using Microsoft.CodeAnalysis.CodeFixes; +using MonoDevelop.CodeIssues; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Text; +using MonoDevelop.Ide.TypeSystem; +using MonoDevelop.Ide; +using Microsoft.CodeAnalysis.CodeActions; +using ICSharpCode.NRefactory6.CSharp.Refactoring; +using MonoDevelop.AnalysisCore; +using MonoDevelop.Ide.Editor; +using MonoDevelop.Components; +using MonoDevelop.Ide.Editor.Extension; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis.Formatting; +using Microsoft.CodeAnalysis; namespace MonoDevelop.CodeActions { - class CodeActionEditorExtension : TextEditorExtension + class CodeActionEditorExtension : TextEditorExtension { uint quickFixTimeout; @@ -52,11 +58,6 @@ namespace MonoDevelop.CodeActions uint menuCloseTimeoutId; FixMenuDescriptor codeActionMenu; - public IEnumerable<CodeAction> Fixes { - get; - private set; - } - static CodeActionEditorExtension () { var usages = PropertyService.Get<Properties> ("CodeActionUsages", new Properties ()); @@ -67,6 +68,7 @@ namespace MonoDevelop.CodeActions void CancelSmartTagPopupTimeout () { + if (smartTagPopupTimeoutId != 0) { GLib.Source.Remove (smartTagPopupTimeoutId); smartTagPopupTimeoutId = 0; @@ -80,27 +82,28 @@ namespace MonoDevelop.CodeActions menuCloseTimeoutId = 0; } } - + void RemoveWidget () { if (currentSmartTag != null) { - document.Editor.Document.RemoveMarker (currentSmartTag); + Editor.RemoveMarker (currentSmartTag); currentSmartTag = null; - currentSmartTagBegin = DocumentLocation.Empty; + currentSmartTagBegin = -1; } CancelSmartTagPopupTimeout (); - } - + public override void Dispose () { CancelMenuCloseTimer (); CancelQuickFixTimer (); - document.Editor.SelectionChanged -= HandleSelectionChanged; - document.DocumentParsed -= HandleDocumentDocumentParsed; - document.Editor.Parent.BeginHover -= HandleBeginHover; + Editor.CaretPositionChanged -= HandleCaretPositionChanged; + Editor.SelectionChanged -= HandleSelectionChanged; + DocumentContext.DocumentParsed -= HandleDocumentDocumentParsed; + Editor.BeginMouseHover -= HandleBeginHover; + Editor.TextChanged -= Editor_TextChanged; + Editor.EndAtomicUndoOperation -= Editor_EndAtomicUndoOperation; RemoveWidget (); - Fixes = null; base.Dispose (); } @@ -108,6 +111,8 @@ namespace MonoDevelop.CodeActions static void ConfirmUsage (string id) { + if (id == null) + return; if (!CodeActionUsages.ContainsKey (id)) { CodeActionUsages [id] = 1; } else { @@ -120,70 +125,137 @@ namespace MonoDevelop.CodeActions internal static int GetUsage (string id) { int result; - if (!CodeActionUsages.TryGetValue (id, out result)) + if (id == null || !CodeActionUsages.TryGetValue (id, out result)) return 0; return result; } public void CancelQuickFixTimer () { - if (quickFixCancellationTokenSource != null) - quickFixCancellationTokenSource.Cancel (); - if (quickFixTimeout != 0) { - GLib.Source.Remove (quickFixTimeout); - quickFixTimeout = 0; - } + quickFixCancellationTokenSource.Cancel (); + quickFixCancellationTokenSource = new CancellationTokenSource (); + smartTagTask = null; } - CancellationTokenSource quickFixCancellationTokenSource; + Task<CodeActionContainer> smartTagTask; + CancellationTokenSource quickFixCancellationTokenSource = new CancellationTokenSource (); - public override void CursorPositionChanged () + void HandleCaretPositionChanged (object sender, EventArgs e) { + if (Editor.IsInAtomicUndo) + return; CancelQuickFixTimer (); - if (QuickTaskStrip.EnableFancyFeatures && Document.ParsedDocument != null && !Debugger.DebuggingService.IsDebugging) { - quickFixCancellationTokenSource = new CancellationTokenSource (); + if (AnalysisOptions.EnableFancyFeatures && DocumentContext.ParsedDocument != null && !Debugger.DebuggingService.IsDebugging) { var token = quickFixCancellationTokenSource.Token; - quickFixTimeout = GLib.Timeout.Add (100, delegate { - var loc = Document.Editor.Caret.Location; - RefactoringService.QueueQuickFixAnalysis (Document, loc, token, delegate(List<CodeAction> fixes) { - if (!fixes.Any ()) { - ICSharpCode.NRefactory.Semantics.ResolveResult resolveResult; - AstNode node; - if (ResolveCommandHandler.ResolveAt (document, out resolveResult, out node, token)) { - var possibleNamespaces = ResolveCommandHandler.GetPossibleNamespaces (document, node, ref resolveResult); - if (!possibleNamespaces.Any ()) { - if (currentSmartTag != null) - Application.Invoke (delegate { RemoveWidget (); }); - return; + var curOffset = Editor.CaretOffset; + foreach (var fix in GetCurrentFixes ().AllValidCodeActions) { + if (!fix.ValidSegment.Contains (curOffset)) { + RemoveWidget (); + break; + } + } + + var loc = Editor.CaretOffset; + var ad = DocumentContext.AnalysisDocument; + if (ad == null) { + return; + } + + TextSpan span; + + if (Editor.IsSomethingSelected) { + var selectionRange = Editor.SelectionRange; + span = selectionRange.Offset >= 0 ? TextSpan.FromBounds (selectionRange.Offset, selectionRange.EndOffset) : TextSpan.FromBounds (loc, loc); + } else { + span = TextSpan.FromBounds (loc, loc); + } + + var diagnosticsAtCaret = + Editor.GetTextSegmentMarkersAt (Editor.CaretOffset) + .OfType<IGenericTextSegmentMarker> () + .Select (rm => rm.Tag) + .OfType<DiagnosticResult> () + .Select (dr => dr.Diagnostic) + .ToList (); + + var errorList = Editor + .GetTextSegmentMarkersAt (Editor.CaretOffset) + .OfType<IErrorMarker> () + .Where (rm => !string.IsNullOrEmpty (rm.Error.Id)).ToList (); + int editorLength = Editor.Length; + + smartTagTask = Task.Run (async delegate { + try { + var codeIssueFixes = new List<ValidCodeDiagnosticAction> (); + var diagnosticIds = diagnosticsAtCaret.Select (diagnostic => diagnostic.Id).Concat (errorList.Select (rm => rm.Error.Id)).ToImmutableArray<string> (); + foreach (var cfp in CodeRefactoringService.GetCodeFixesAsync (DocumentContext, CodeRefactoringService.MimeTypeToLanguage (Editor.MimeType)).Result) { + if (token.IsCancellationRequested) + return CodeActionContainer.Empty; + var provider = cfp.GetCodeFixProvider (); + if (!provider.FixableDiagnosticIds.Any (diagnosticIds.Contains)) + continue; + try { + var groupedDiagnostics = diagnosticsAtCaret + .Concat (errorList.Select (em => em.Error.Tag) + .OfType<Diagnostic> ()) + .GroupBy (d => d.Location.SourceSpan); + foreach (var g in groupedDiagnostics) { + var diagnosticSpan = g.Key; + + var validDiagnostics = g.Where (d => provider.FixableDiagnosticIds.Contains (d.Id)).ToImmutableArray (); + if (validDiagnostics.Length == 0) + continue; + await provider.RegisterCodeFixesAsync (new CodeFixContext(ad, diagnosticSpan, validDiagnostics, (ca, d) => codeIssueFixes.Add (new ValidCodeDiagnosticAction (cfp, ca, diagnosticSpan)), token)); + + // TODO: Is that right ? Currently it doesn't really make sense to run one code fix provider on several overlapping diagnostics at the same location + // However the generate constructor one has that case and if I run it twice the same code action is generated twice. So there is a dupe check problem there. + // Work around for now is to only take the first diagnostic batch. + break; } - } else { - if (currentSmartTag != null) - Application.Invoke (delegate { RemoveWidget (); }); - return; + } catch (OperationCanceledException) { + return CodeActionContainer.Empty; + } catch (AggregateException ae) { + ae.Flatten ().Handle (aex => aex is OperationCanceledException); + return CodeActionContainer.Empty; + } catch (Exception ex) { + LoggingService.LogError ("Error while getting refactorings from code fix provider " + cfp.Name, ex); + continue; } } + var codeActions = new List<ValidCodeAction> (); + foreach (var action in CodeRefactoringService.GetValidActionsAsync (Editor, DocumentContext, span, token).Result) { + codeActions.Add (action); + } + var codeActionContainer = new CodeActionContainer (codeIssueFixes, codeActions, diagnosticsAtCaret); Application.Invoke (delegate { if (token.IsCancellationRequested) return; - CreateSmartTag (fixes, loc); + if (codeActionContainer.IsEmpty) { + RemoveWidget (); + return; + } + CreateSmartTag (codeActionContainer, loc); }); - }); - quickFixTimeout = 0; - return false; - }); + return codeActionContainer; + + } catch (AggregateException ae) { + ae.Flatten ().Handle (aex => aex is OperationCanceledException); + return CodeActionContainer.Empty; + } catch (OperationCanceledException) { + return CodeActionContainer.Empty; + } + }, token); } else { RemoveWidget (); } - base.CursorPositionChanged (); } - internal static bool IsAnalysisOrErrorFix (CodeAction act) + internal static bool IsAnalysisOrErrorFix (Microsoft.CodeAnalysis.CodeActions.CodeAction act) { - return act is AnalysisContextActionProvider.AnalysisCodeAction || act.Severity == Severity.Error; - } - + return false; + } - class FixMenuEntry + internal class FixMenuEntry { public static readonly FixMenuEntry Separator = new FixMenuEntry ("-", null); public readonly string Label; @@ -197,12 +269,14 @@ namespace MonoDevelop.CodeActions } } - class FixMenuDescriptor : FixMenuEntry + internal class FixMenuDescriptor : FixMenuEntry { readonly List<FixMenuEntry> items = new List<FixMenuEntry> (); - public IReadOnlyList<FixMenuEntry> Items { - get { + public IReadOnlyList<FixMenuEntry> Items + { + get + { return items; } } @@ -217,93 +291,56 @@ namespace MonoDevelop.CodeActions public void Add (FixMenuEntry entry) { - items.Add (entry); + items.Add (entry); } - public object MotionNotifyEvent { + public object MotionNotifyEvent + { get; set; } } + internal static Action<TextEditor, DocumentContext, FixMenuDescriptor> AddPossibleNamespace; + void PopupQuickFixMenu (Gdk.EventButton evt, Action<FixMenuDescriptor> menuAction) { FixMenuDescriptor menu = new FixMenuDescriptor (); var fixMenu = menu; - ResolveResult resolveResult; - ICSharpCode.NRefactory.CSharp.AstNode node; + //ResolveResult resolveResult; + //ICSharpCode.NRefactory.CSharp.AstNode node; int items = 0; - if (ResolveCommandHandler.ResolveAt (document, out resolveResult, out node)) { - var possibleNamespaces = MonoDevelop.Refactoring.ResolveCommandHandler.GetPossibleNamespaces ( - document, - node, - ref resolveResult - ); - - foreach (var t in possibleNamespaces.Where (tp => tp.OnlyAddReference)) { - menu.Add (new FixMenuEntry (t.GetImportText (), delegate { - new ResolveCommandHandler.AddImport (document, resolveResult, null, t.Reference, true, node).Run (); - })); - items++; - } - bool addUsing = !(resolveResult is AmbiguousTypeResolveResult); - if (addUsing) { - foreach (var t in possibleNamespaces.Where (tp => tp.IsAccessibleWithGlobalUsing)) { - string ns = t.Namespace; - var reference = t.Reference; - menu.Add (new FixMenuEntry (t.GetImportText (), - delegate { - new ResolveCommandHandler.AddImport (document, resolveResult, ns, reference, true, node).Run (); - }) - ); - items++; - } - } +// if (AddPossibleNamespace != null) { +// AddPossibleNamespace (Editor, DocumentContext, menu); +// items = menu.Items.Count; +// } - bool resolveDirect = !(resolveResult is UnknownMemberResolveResult); - if (resolveDirect) { - foreach (var t in possibleNamespaces) { - string ns = t.Namespace; - var reference = t.Reference; - menu.Add (new FixMenuEntry (t.GetInsertNamespaceText (document.Editor.GetTextBetween (node.StartLocation, node.EndLocation)), - delegate { - new ResolveCommandHandler.AddImport (document, resolveResult, ns, reference, false, node).Run (); - })); - items++; - } - } - - if (menu.Items.Any () && Fixes.Any ()) { - fixMenu = new FixMenuDescriptor (GettextCatalog.GetString ("Quick Fixes")); - menu.Add (fixMenu); - items++; - } - } PopulateFixes (fixMenu, ref items); + if (items == 0) { return; } - document.Editor.SuppressTooltips = true; - document.Editor.Parent.HideTooltip (); +// document.Editor.SuppressTooltips = true; +// document.Editor.Parent.HideTooltip (); if (menuAction != null) menuAction (menu); - var container = document.Editor.Parent; - var p = container.LocationToPoint (currentSmartTagBegin); + var p = Editor.LocationToPoint (Editor.OffsetToLocation (currentSmartTagBegin)); + Gtk.Widget widget = Editor; var rect = new Gdk.Rectangle ( - p.X + container.Allocation.X , - p.Y + (int)document.Editor.LineHeight + container.Allocation.Y, 0, 0); + (int)p.X + widget.Allocation.X, + (int)p.Y + (int)Editor.LineHeight + widget.Allocation.Y, 0, 0); - ShowFixesMenu (document.Editor.Parent, rect, menu); + ShowFixesMenu (widget, rect, menu); } - #if MAC +#if MAC class ClosingMenuDelegate : AppKit.NSMenuDelegate { - readonly TextEditorData data; + readonly TextEditor data; - public ClosingMenuDelegate (TextEditorData editor_data) + public ClosingMenuDelegate (TextEditor editor_data) { data = editor_data; } @@ -314,10 +351,11 @@ namespace MonoDevelop.CodeActions public override void MenuDidClose (AppKit.NSMenu menu) { - data.SuppressTooltips = false; + // TODO: roslyn port ? (seems to be unused anyways btw.) + //data.SuppressTooltips = false; } } - #endif +#endif bool ShowFixesMenu (Gtk.Widget parent, Gdk.Rectangle evt, FixMenuDescriptor entrySet) { @@ -325,6 +363,7 @@ namespace MonoDevelop.CodeActions return true; try { #if MAC + Gtk.Application.Invoke (delegate { parent.GrabFocus (); int x, y; x = (int)evt.X; @@ -332,7 +371,7 @@ namespace MonoDevelop.CodeActions // Explicitly release the grab because the menu is shown on the mouse position, and the widget doesn't get the mouse release event Gdk.Pointer.Ungrab (Gtk.Global.CurrentEventTime); var menu = CreateNSMenu (entrySet); - menu.Delegate = new ClosingMenuDelegate (document.Editor); + menu.Delegate = new ClosingMenuDelegate (Editor); var nsview = MonoDevelop.Components.Mac.GtkMacInterop.GetNSView (parent); var toplevel = parent.Toplevel as Gtk.Window; int trans_x, trans_y; @@ -351,18 +390,20 @@ namespace MonoDevelop.CodeActions null, 0, 0, 0); AppKit.NSMenu.PopUpContextMenu (menu, tmp_event, nsview); + }); #else var menu = CreateGtkMenu (entrySet); menu.Events |= Gdk.EventMask.AllEventsMask; menu.SelectFirst (true); menu.Hidden += delegate { - document.Editor.SuppressTooltips = false; + // document.Editor.SuppressTooltips = false; }; menu.ShowAll (); menu.SelectFirst (true); menu.MotionNotifyEvent += (o, args) => { - if (args.Event.Window == Editor.Parent.TextArea.GdkWindow) { + Gtk.Widget widget = Editor; + if (args.Event.Window == widget.GdkWindow) { StartMenuCloseTimer (); } else { CancelMenuCloseTimer (); @@ -376,7 +417,8 @@ namespace MonoDevelop.CodeActions } return true; } - #if MAC + +#if MAC AppKit.NSMenu CreateNSMenu (FixMenuDescriptor entrySet) { @@ -401,28 +443,28 @@ namespace MonoDevelop.CodeActions } return menu; } - #endif +#endif static Menu CreateGtkMenu (FixMenuDescriptor entrySet) { var menu = new Menu (); foreach (var item in entrySet.Items) { if (item == FixMenuEntry.Separator) { - menu.Add (new SeparatorMenuItem ()); + menu.Add (new SeparatorMenuItem ()); continue; } var subMenu = item as FixMenuDescriptor; if (subMenu != null) { var gtkSubMenu = new Gtk.MenuItem (item.Label); gtkSubMenu.Submenu = CreateGtkMenu (subMenu); - menu.Add (gtkSubMenu); + menu.Add (gtkSubMenu); continue; } var menuItem = new Gtk.MenuItem (item.Label); menuItem.Activated += delegate { item.Action (); }; - menu.Add (menuItem); + menu.Add (menuItem); } return menu; } @@ -431,275 +473,297 @@ namespace MonoDevelop.CodeActions { int mnemonic = 1; bool gotImportantFix = false, addedSeparator = false; - var fixesAdded = new List<string> (); - foreach (var fix_ in Fixes.OrderByDescending (i => Tuple.Create (IsAnalysisOrErrorFix(i), (int)i.Severity, GetUsage (i.IdString)))) { + foreach (var fix_ in GetCurrentFixes ().CodeFixActions.OrderByDescending (i => Tuple.Create (IsAnalysisOrErrorFix (i.CodeAction), (int)0, GetUsage (i.CodeAction.EquivalenceKey)))) { // filter out code actions that are already resolutions of a code issue - if (fixesAdded.Any (f => fix_.IdString.IndexOf (f, StringComparison.Ordinal) >= 0)) - continue; - fixesAdded.Add (fix_.IdString); - if (IsAnalysisOrErrorFix (fix_)) + if (IsAnalysisOrErrorFix (fix_.CodeAction)) gotImportantFix = true; - if (!addedSeparator && gotImportantFix && !IsAnalysisOrErrorFix(fix_)) { + if (!addedSeparator && gotImportantFix && !IsAnalysisOrErrorFix (fix_.CodeAction)) { menu.Add (FixMenuEntry.Separator); addedSeparator = true; } var fix = fix_; - var escapedLabel = fix.Title.Replace ("_", "__"); + var escapedLabel = fix.CodeAction.Title.Replace ("_", "__"); var label = (mnemonic <= 10) ? "_" + (mnemonic++ % 10).ToString () + " " + escapedLabel : " " + escapedLabel; var thisInstanceMenuItem = new FixMenuEntry (label, delegate { - new ContextActionRunner (fix, document, currentSmartTagBegin).Run (null, EventArgs.Empty); - ConfirmUsage (fix.IdString); + new ContextActionRunner (fix.CodeAction, Editor, DocumentContext).Run (null, EventArgs.Empty); + ConfirmUsage (fix.CodeAction.EquivalenceKey); }); menu.Add (thisInstanceMenuItem); items++; } bool first = true; - var settingsMenuFixes = Fixes - .OfType<AnalysisContextActionProvider.AnalysisCodeAction> () - .Where (f => f.Result is InspectorResults) - .GroupBy (f => ((InspectorResults)f.Result).Inspector); - foreach (var analysisFixGroup_ in settingsMenuFixes) { - var analysisFixGroup = analysisFixGroup_; - var arbitraryFixInGroup = analysisFixGroup.First (); - var ir = (InspectorResults)arbitraryFixInGroup.Result; - + foreach (var fix in GetCurrentFixes ().CodeRefactoringActions) { if (first) { - menu.Add (FixMenuEntry.Separator); + if (items > 0) + menu.Add (FixMenuEntry.Separator); first = false; } - var subMenu = new FixMenuDescriptor (); - foreach (var analysisFix_ in analysisFixGroup) { - var analysisFix = analysisFix_; - if (analysisFix.SupportsBatchRunning) { - var batchRunMenuItem = new FixMenuEntry ( - string.Format (GettextCatalog.GetString ("Apply in file: {0}"), analysisFix.Title), - delegate { - ConfirmUsage (analysisFix.IdString); - new ContextActionRunner (analysisFix, document, this.currentSmartTagBegin).BatchRun (null, EventArgs.Empty); - } - ); - subMenu.Add (batchRunMenuItem); - subMenu.Add (FixMenuEntry.Separator); - } - } - - var inspector = ir.Inspector; - if (inspector.CanSuppressWithAttribute) { - var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with attribute"), - delegate { - inspector.SuppressWithAttribute (document, arbitraryFixInGroup.DocumentRegion); - }); - subMenu.Add (menuItem); - } + var escapedLabel = fix.CodeAction.Title.Replace ("_", "__"); + var label = (mnemonic <= 10) + ? "_" + (mnemonic++ % 10).ToString () + " " + escapedLabel + : " " + escapedLabel; + var thisInstanceMenuItem = new FixMenuEntry (label, delegate { + new ContextActionRunner (fix.CodeAction, Editor, DocumentContext).Run (null, EventArgs.Empty); + ConfirmUsage (fix.CodeAction.EquivalenceKey); + }); + menu.Add (thisInstanceMenuItem); + items++; + } - if (inspector.CanDisableWithPragma) { - var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with #pragma"), - delegate { - inspector.DisableWithPragma (document, arbitraryFixInGroup.DocumentRegion); - }); - subMenu.Add (menuItem); - } + first = false; + foreach (var fix_ in GetCurrentFixes ().DiagnosticsAtCaret) { + var fix = fix_; + var label = GettextCatalog.GetString ("_Options for \"{0}\"", fix.GetMessage ()); + var subMenu = new FixMenuDescriptor (label); - if (inspector.CanDisableOnce) { - var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Disable Once"), - delegate { - inspector.DisableOnce (document, arbitraryFixInGroup.DocumentRegion); - }); - subMenu.Add (menuItem); + CodeDiagnosticDescriptor descriptor = BuiltInCodeDiagnosticProvider.GetCodeDiagnosticDescriptor (fix.Id); + if (descriptor == null) + continue; + if (first) { + menu.Add (FixMenuEntry.Separator); + first = false; } - - if (inspector.CanDisableAndRestore) { - var menuItem = new FixMenuEntry (GettextCatalog.GetString ("Disable _and Restore"), + // if (inspector.CanSuppressWithAttribute) { + // var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with attribute"), + // delegate { + // + // inspector.SuppressWithAttribute (Editor, DocumentContext, GetTextSpan (fix.Item2)); + // }); + // subMenu.Add (menuItem); + // } + + if (descriptor.CanDisableWithPragma) { + var menuItem = new FixMenuEntry (GettextCatalog.GetString ("_Suppress with #pragma"), delegate { - inspector.DisableAndRestore (document, arbitraryFixInGroup.DocumentRegion); + descriptor.DisableWithPragma (Editor, DocumentContext, fix.Location.SourceSpan); }); subMenu.Add (menuItem); } - var label = GettextCatalog.GetString ("_Options for \"{0}\"", InspectorResults.GetTitle (ir.Inspector)); - var subMenuItem = new FixMenuDescriptor (label); var optionsMenuItem = new FixMenuEntry (GettextCatalog.GetString ("_Configure Rule"), delegate { - arbitraryFixInGroup.ShowOptions (null, EventArgs.Empty); + IdeApp.Workbench.ShowGlobalPreferencesDialog (null, "C#", dialog => { + var panel = dialog.GetPanel<CodeIssuePanel> ("C#"); + if (panel == null) + return; + panel.Widget.SelectCodeIssue (descriptor.IdString); + }); }); - subMenuItem.Add (optionsMenuItem); + subMenu.Add (optionsMenuItem); - menu.Add (subMenuItem); + menu.Add (subMenu); items++; } } - - class ContextActionRunner + internal class ContextActionRunner { - CodeAction act; - Document document; - TextLocation loc; + readonly CodeAction act; + TextEditor editor; + DocumentContext documentContext; - public ContextActionRunner (MonoDevelop.CodeActions.CodeAction act, MonoDevelop.Ide.Gui.Document document, ICSharpCode.NRefactory.TextLocation loc) + public ContextActionRunner (CodeAction act, TextEditor editor, DocumentContext documentContext) { + this.editor = editor; this.act = act; - this.document = document; - this.loc = loc; + this.documentContext = documentContext; } public void Run (object sender, EventArgs e) { - var context = document.ParsedDocument.CreateRefactoringContext (document, CancellationToken.None); - RefactoringService.ApplyFix (act, context); + Run (); } - public void BatchRun (object sender, EventArgs e) + internal async void Run () { - act.BatchRun (document, loc); - } - } + var token = default(CancellationToken); + var insertionAction = act as InsertionAction; + if (insertionAction != null) { + var insertion = await insertionAction.CreateInsertion (token).ConfigureAwait (false); + + var document = IdeApp.Workbench.OpenDocument (insertion.Location.SourceTree.FilePath); + var parsedDocument = document.UpdateParseDocument (); + if (parsedDocument != null) { + var insertionPoints = InsertionPointService.GetInsertionPoints ( + document.Editor, + parsedDocument, + insertion.Type, + insertion.Location + ); + + var options = new InsertionModeOptions ( + insertionAction.Title, + insertionPoints, + async point => { + if (!point.Success) + return; - class SmartTagMarker : TextSegmentMarker, IActionTextLineMarker - { - CodeActionEditorExtension codeActionEditorExtension; - internal List<CodeAction> fixes; - DocumentLocation loc; + var node = Formatter.Format (insertion.Node, TypeSystemService.Workspace, document.GetOptionSet (), token); - public SmartTagMarker (int offset, CodeActionEditorExtension codeActionEditorExtension, List<CodeAction> fixes, DocumentLocation loc) : base (offset, 0) - { - this.codeActionEditorExtension = codeActionEditorExtension; - this.fixes = fixes; - this.loc = loc; - } - - public SmartTagMarker (int offset) : base (offset, 0) - { - } - const double tagMarkerWidth = 8; - const double tagMarkerHeight = 2; - public override void Draw (TextEditor editor, Cairo.Context cr, Pango.Layout layout, bool selected, int startOffset, int endOffset, double y, double startXPos, double endXPos) - { - var line = editor.GetLine (loc.Line); - var x = editor.ColumnToX (line, loc.Column) - editor.HAdjustment.Value + editor.TextViewMargin.XOffset + editor.TextViewMargin.TextStartPosition; + point.InsertionPoint.Insert (document.Editor, document, node.ToString ()); + // document = await Simplifier.ReduceAsync(document.AnalysisDocument, Simplifier.Annotation, cancellationToken: token).ConfigureAwait(false); - cr.Rectangle (Math.Floor (x) + 0.5, Math.Floor (y) + 0.5 + (line == editor.GetLineByOffset (startOffset) ? editor.LineHeight - tagMarkerHeight - 1 : 0), tagMarkerWidth * cr.LineWidth, tagMarkerHeight * cr.LineWidth); + } + ); - if (HslColor.Brightness (editor.ColorStyle.PlainText.Background) < 0.5) { - cr.SetSourceRGBA (0.8, 0.8, 1, 0.9); - } else { - cr.SetSourceRGBA (0.2, 0.2, 1, 0.9); + document.Editor.StartInsertionMode (options); + return; + } } - cr.Stroke (); - } - - #region IActionTextLineMarker implementation - bool IActionTextLineMarker.MousePressed (TextEditor editor, MarginMouseEventArgs args) - { - return false; + var oldSolution = documentContext.AnalysisDocument.Project.Solution; + var updatedSolution = oldSolution; + foreach (var operation in act.GetOperationsAsync (token).Result) { + var applyChanges = operation as ApplyChangesOperation; + if (applyChanges == null) { + operation.Apply (documentContext.RoslynWorkspace, token); + continue; + } + if (updatedSolution == oldSolution) { + updatedSolution = applyChanges.ChangedSolution; + } + operation.Apply (documentContext.RoslynWorkspace, token); + } + TryStartRenameSession (documentContext.RoslynWorkspace, oldSolution, updatedSolution, token); } - void IActionTextLineMarker.MouseHover (TextEditor editor, MarginMouseEventArgs args, TextLineMarkerHoverResult result) + static IEnumerable<DocumentId> GetChangedDocuments (Solution newSolution, Solution oldSolution) { - if (args.Button != 0) - return; - var line = editor.GetLine (loc.Line); - if (line == null) - return; - var x = editor.ColumnToX (line, loc.Column) - editor.HAdjustment.Value + editor.TextViewMargin.TextStartPosition; - var y = editor.LineToY (line.LineNumber + 1) - editor.VAdjustment.Value; - const double xAdditionalSpace = tagMarkerWidth; - if (args.X - x >= -xAdditionalSpace * editor.Options.Zoom && - args.X - x < (tagMarkerWidth + xAdditionalSpace) * editor.Options.Zoom /*&& - args.Y - y < (editor.LineHeight / 2) * editor.Options.Zoom*/) { - result.Cursor = null; - Popup (); - } else { - codeActionEditorExtension.CancelSmartTagPopupTimeout (); + if (newSolution != null) { + var solutionChanges = newSolution.GetChanges (oldSolution); + foreach (var projectChanges in solutionChanges.GetProjectChanges ()) { + foreach (var documentId in projectChanges.GetChangedDocuments ()) { + yield return documentId; + } + } } } - public void Popup () + async void TryStartRenameSession (Workspace workspace, Solution oldSolution, Solution newSolution, CancellationToken cancellationToken) { - codeActionEditorExtension.smartTagPopupTimeoutId = GLib.Timeout.Add (menuTimeout, delegate { - codeActionEditorExtension.PopupQuickFixMenu (null, menu => { - codeActionEditorExtension.codeActionMenu = menu; - }); - codeActionEditorExtension.smartTagPopupTimeoutId = 0; - return false; - }); + var changedDocuments = GetChangedDocuments (newSolution, oldSolution); + foreach (var documentId in changedDocuments) { + var document = newSolution.GetDocument (documentId); + var root = await document.GetSyntaxRootAsync (cancellationToken).ConfigureAwait (false); + + SyntaxToken? renameTokenOpt = root.GetAnnotatedNodesAndTokens (RenameAnnotation.Kind) + .Where (s => s.IsToken) + .Select (s => s.AsToken ()) + .Cast<SyntaxToken?> () + .FirstOrDefault (); + + if (renameTokenOpt.HasValue) { + var latestDocument = workspace.CurrentSolution.GetDocument (documentId); + var latestModel = await latestDocument.GetSemanticModelAsync (cancellationToken).ConfigureAwait (false); + var latestRoot = await latestDocument.GetSyntaxRootAsync (cancellationToken).ConfigureAwait (false); + Application.Invoke (delegate { + try { + var node = latestRoot.FindNode (renameTokenOpt.Value.Parent.Span, false, false); + if (node == null) + return; + var info = latestModel.GetSymbolInfo (node); + var sym = info.Symbol ?? latestModel.GetDeclaredSymbol (node); + if (sym != null) + new MonoDevelop.Refactoring.Rename.RenameRefactoring ().Rename (sym); + } catch (Exception ex) { + LoggingService.LogError ("Error while renaming " + renameTokenOpt.Value.Parent, ex); + } + }); + return; + } + } } - - - #endregion } - SmartTagMarker currentSmartTag; - DocumentLocation currentSmartTagBegin; - void CreateSmartTag (List<CodeAction> fixes, DocumentLocation loc) + ISmartTagMarker currentSmartTag; + int currentSmartTagBegin; + + void CreateSmartTag (CodeActionContainer fixes, int offset) { - Fixes = fixes; - if (!QuickTaskStrip.EnableFancyFeatures) { + if (!AnalysisOptions.EnableFancyFeatures || fixes.IsEmpty) { RemoveWidget (); return; } - var editor = document.Editor; - if (editor == null || editor.Parent == null || !editor.Parent.IsRealized) { + var editor = Editor; + if (editor == null) { RemoveWidget (); return; } - if (document.ParsedDocument == null || document.ParsedDocument.IsInvalid) { + if (DocumentContext.ParsedDocument == null || DocumentContext.ParsedDocument.IsInvalid) { RemoveWidget (); return; } - var container = editor.Parent; - if (container == null) { - RemoveWidget (); - return; - } +// var container = editor.Parent; +// if (container == null) { +// RemoveWidget (); +// return; +// } bool first = true; - DocumentLocation smartTagLocBegin = loc; - foreach (var fix in fixes) { - if (fix.DocumentRegion.IsEmpty) + var smartTagLocBegin = offset; + foreach (var fix in fixes.CodeFixActions.Concat (fixes.CodeRefactoringActions)) { + var textSpan = fix.ValidSegment; + if (textSpan.IsEmpty) continue; - if (first || loc < fix.DocumentRegion.Begin) { - smartTagLocBegin = fix.DocumentRegion.Begin; + if (first || offset < textSpan.Start) { + smartTagLocBegin = textSpan.Start; } first = false; } - if (smartTagLocBegin.Line != loc.Line) - smartTagLocBegin = new DocumentLocation (loc.Line, 1); +// if (smartTagLocBegin.Line != loc.Line) +// smartTagLocBegin = new DocumentLocation (loc.Line, 1); // got no fix location -> try to search word start - if (first) { - int offset = document.Editor.LocationToOffset (smartTagLocBegin); - while (offset > 0) { - char ch = document.Editor.GetCharAt (offset - 1); - if (!char.IsLetterOrDigit (ch) && ch != '_') - break; - offset--; - } - smartTagLocBegin = document.Editor.OffsetToLocation (offset); - } +// if (first) { +// int offset = document.Editor.LocationToOffset (smartTagLocBegin); +// while (offset > 0) { +// char ch = document.Editor.GetCharAt (offset - 1); +// if (!char.IsLetterOrDigit (ch) && ch != '_') +// break; +// offset--; +// } +// smartTagLocBegin = document.Editor.OffsetToLocation (offset); +// } if (currentSmartTag != null && currentSmartTagBegin == smartTagLocBegin) { - currentSmartTag.fixes = fixes; return; } RemoveWidget (); currentSmartTagBegin = smartTagLocBegin; - var line = document.Editor.GetLine (smartTagLocBegin.Line); - currentSmartTag = new SmartTagMarker ((line.NextLine ?? line).Offset, this, fixes, smartTagLocBegin); - document.Editor.Document.AddMarker (currentSmartTag); + var realLoc = Editor.OffsetToLocation (smartTagLocBegin); + + currentSmartTag = TextMarkerFactory.CreateSmartTagMarker (Editor, smartTagLocBegin, realLoc); + currentSmartTag.Tag = fixes; + editor.AddMarker (currentSmartTag); } - - public override void Initialize () + + protected override void Initialize () { base.Initialize (); - document.DocumentParsed += HandleDocumentDocumentParsed; - document.Editor.SelectionChanged += HandleSelectionChanged; - document.Editor.Parent.BeginHover += HandleBeginHover; + DocumentContext.DocumentParsed += HandleDocumentDocumentParsed; + Editor.SelectionChanged += HandleSelectionChanged; + Editor.BeginMouseHover += HandleBeginHover; + Editor.CaretPositionChanged += HandleCaretPositionChanged; + Editor.TextChanged += Editor_TextChanged; + Editor.EndAtomicUndoOperation += Editor_EndAtomicUndoOperation; + } + + void Editor_EndAtomicUndoOperation (object sender, EventArgs e) + { + RemoveWidget (); + HandleCaretPositionChanged (null, EventArgs.Empty); + } + + void Editor_TextChanged (object sender, MonoDevelop.Core.Text.TextChangeEventArgs e) + { + if (Editor.IsInAtomicUndo) + return; + RemoveWidget (); + HandleCaretPositionChanged (null, EventArgs.Empty); } void HandleBeginHover (object sender, EventArgs e) @@ -723,43 +787,54 @@ namespace MonoDevelop.CodeActions void HandleSelectionChanged (object sender, EventArgs e) { - CursorPositionChanged (); + HandleCaretPositionChanged (null, EventArgs.Empty); } - + void HandleDocumentDocumentParsed (object sender, EventArgs e) { - CursorPositionChanged (); + HandleCaretPositionChanged (null, EventArgs.Empty); } - + [CommandUpdateHandler(RefactoryCommands.QuickFix)] public void UpdateQuickFixCommand (CommandInfo ci) { - if (QuickTaskStrip.EnableFancyFeatures) { + if (AnalysisOptions.EnableFancyFeatures) { ci.Enabled = currentSmartTag != null; } else { ci.Enabled = true; } } - + + void CurrentSmartTagPopup () + { + CancelSmartTagPopupTimeout (); + smartTagPopupTimeoutId = GLib.Timeout.Add (menuTimeout, delegate { + PopupQuickFixMenu (null, menu => { + codeActionMenu = menu; + }); + smartTagPopupTimeoutId = 0; + return false; + }); + } + [CommandHandler(RefactoryCommands.QuickFix)] void OnQuickFixCommand () { - if (!QuickTaskStrip.EnableFancyFeatures) { - Fixes = RefactoringService.GetValidActions (Document, Document.Editor.Caret.Location); - currentSmartTagBegin = Document.Editor.Caret.Location; - PopupQuickFixMenu (null, null); + if (!AnalysisOptions.EnableFancyFeatures) { + //Fixes = RefactoringService.GetValidActions (Editor, DocumentContext, Editor.CaretLocation).Result; + currentSmartTagBegin = Editor.CaretOffset; + PopupQuickFixMenu (null, null); return; } if (currentSmartTag == null) return; - currentSmartTag.Popup (); + CurrentSmartTagPopup (); } - static readonly List<CodeAction> emptyList = new List<CodeAction> (); - internal List<CodeAction> GetCurrentFixes () + internal CodeActionContainer GetCurrentFixes () { - return currentSmartTag == null ? emptyList : currentSmartTag.fixes; + return smartTagTask == null ? CodeActionContainer.Empty : smartTagTask.Result; } } -}
\ No newline at end of file +} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionPanelWidget.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionPanelWidget.cs index 66f132a1c5..c74d775caa 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionPanelWidget.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionPanelWidget.cs @@ -32,6 +32,7 @@ using System.Text; using MonoDevelop.Refactoring; using System.Collections.Generic; using GLib; +using MonoDevelop.CodeIssues; namespace MonoDevelop.CodeActions { @@ -54,14 +55,14 @@ namespace MonoDevelop.CodeActions { readonly string mimeType; - readonly TreeStore treeStore = new TreeStore (typeof(string), typeof(bool), typeof(CodeActionProvider), typeof(string)); - readonly Dictionary<CodeActionProvider, bool> providerStates = new Dictionary<CodeActionProvider, bool> (); + readonly TreeStore treeStore = new TreeStore (typeof(string), typeof(bool), typeof(CodeRefactoringDescriptor)); + readonly Dictionary<CodeRefactoringDescriptor, bool> providerStates = new Dictionary<CodeRefactoringDescriptor, bool> (); void GetAllProviderStates () { - string disabledNodes = PropertyService.Get ("ContextActions." + mimeType, ""); - foreach (var node in RefactoringService.ContextAddinNodes.Where (n => n.MimeType == mimeType)) { - providerStates [node] = disabledNodes.IndexOf (node.IdString, StringComparison.Ordinal) < 0; + var language = CodeRefactoringService.MimeTypeToLanguage (mimeType); + foreach (var node in BuiltInCodeDiagnosticProvider.GetBuiltInCodeRefactoringDescriptorsAsync (CodeRefactoringService.MimeTypeToLanguage(language), true).Result) { + providerStates [node] = node.IsEnabled; } } @@ -94,7 +95,7 @@ namespace MonoDevelop.CodeActions TreeIter iter; if (!treeStore.GetIterFromString (out iter, args.Path)) return; - var provider = (CodeActionProvider)treeStore.GetValue (iter, 2); + var provider = (CodeRefactoringDescriptor)treeStore.GetValue (iter, 2); providerStates [provider] = !providerStates [provider]; treeStore.SetValue (iter, 1, providerStates [provider]); }; @@ -125,26 +126,20 @@ namespace MonoDevelop.CodeActions { treeStore.Clear (); var sortedAndFiltered = providerStates.Keys - .Where (node => string.IsNullOrEmpty (filter) || node.Title.IndexOf (filter, StringComparison.OrdinalIgnoreCase) > 0) - .OrderBy (n => n.Title, StringComparer.Ordinal); + .Where (node => string.IsNullOrEmpty (filter) || node.Name.IndexOf (filter, StringComparison.OrdinalIgnoreCase) > 0) + .OrderBy (n => n.Name, StringComparer.Ordinal); foreach (var node in sortedAndFiltered) { - var title = node.Title; + var title = node.Name; MonoDevelop.CodeIssues.CodeIssuePanelWidget.MarkupSearchResult (filter, ref title); - treeStore.AppendValues (title, providerStates [node], node, node.Description); + treeStore.AppendValues (title, providerStates [node], node); } } public void ApplyChanges () { - var sb = new StringBuilder (); foreach (var kv in providerStates) { - if (kv.Value) - continue; - if (sb.Length > 0) - sb.Append (","); - sb.Append (kv.Key.IdString); + kv.Key.IsEnabled = kv.Value; } - PropertyService.Set ("ContextActions." + mimeType, sb.ToString ()); } } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionProvider.cs deleted file mode 100644 index 32c1c7d1ec..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeActionProvider.cs +++ /dev/null @@ -1,74 +0,0 @@ -// -// ContextActionProvider.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory; -using System.Threading; -using System.Collections.Generic; -using System; - -namespace MonoDevelop.CodeActions -{ - /// <summary> - /// A code action provider is a factory that creates code actions for a document at a given location. - /// Note: There is only one code action provider generated therfore providers need to be state less. - /// </summary> - public abstract class CodeActionProvider - { - /// <summary> - /// Gets or sets the type of the MIME the provider is attached to. - /// </summary> - public string MimeType { get; set; } - - /// <summary> - /// Gets or sets the category of the provider (used in the option panel). - /// </summary> - public string Category { get; set; } - - /// <summary> - /// Gets or sets the title of the provider (used in the option panel). - /// </summary> - public string Title { get; set; } - - /// <summary> - /// Gets or sets the description of the provider (used in the option panel). - /// </summary> - public string Description { get; set; } - - /// <summary> - /// Gets the identifier string used as property ID tag. - /// </summary> - public virtual string IdString { - get { - return GetType ().FullName; - } - } - - /// <summary> - /// Gets all the code actions in document at given location. - /// </summary> - public abstract IEnumerable<CodeAction> GetActions (MonoDevelop.Ide.Gui.Document document, object refactoringContext, TextLocation loc, CancellationToken cancellationToken); - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeRefactoringDescriptor.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeRefactoringDescriptor.cs new file mode 100644 index 0000000000..c845671203 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeRefactoringDescriptor.cs @@ -0,0 +1,101 @@ +// +// CodeActionDescriptor.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Microsoft.CodeAnalysis.CodeRefactorings; +using MonoDevelop.Core; +using System.Linq; + +namespace MonoDevelop.CodeActions +{ + /// <summary> + /// This class wraps a roslyn <see cref="ICodeRefactoringProvider"/> and adds required meta data to it. + /// </summary> + class CodeRefactoringDescriptor + { + readonly Type codeActionType; + readonly ExportCodeRefactoringProviderAttribute attr; + + CodeRefactoringProvider instance; + + /// <summary> + /// Gets the identifier string. + /// </summary> + internal string IdString { + get { + return codeActionType.FullName; + } + } + + /// <summary> + /// Gets the display name for this action. + /// </summary> + public string Name { get { return attr.Name; } } + + /// <summary> + /// Gets the language for this action. + /// </summary> + public string Language { get { return attr.Languages.FirstOrDefault (); } } + + /// <summary> + /// Gets or sets a value indicating whether this code action is enabled by the user. + /// </summary> + /// <value><c>true</c> if this code action is enabled; otherwise, <c>false</c>.</value> + public bool IsEnabled { + get { + return PropertyService.Get ("CodeActions." + Language + "." + IdString, true); + } + set { + PropertyService.Set ("CodeActions." + Language + "." + IdString, value); + } + } + + internal CodeRefactoringDescriptor (Type codeActionType, ExportCodeRefactoringProviderAttribute attr) + { + if (codeActionType == null) + throw new ArgumentNullException ("codeActionType"); + if (attr == null) + throw new ArgumentNullException ("attr"); + this.codeActionType = codeActionType; + this.attr = attr; + } + + /// <summary> + /// Gets the roslyn code action provider. + /// </summary> + public CodeRefactoringProvider GetProvider () + { + if (instance == null) + instance = (CodeRefactoringProvider)Activator.CreateInstance (codeActionType); + return instance; + } + + public override string ToString () + { + return string.Format ("[CodeActionDescriptor: IdString={0}, Name={1}, Language={2}]", IdString, Name, Language); + } + } +} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeRefactoringService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeRefactoringService.cs new file mode 100644 index 0000000000..38b246031f --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/CodeRefactoringService.cs @@ -0,0 +1,157 @@ +// +// CodeActionService.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Microsoft.CodeAnalysis.CodeRefactorings; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Threading; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using MonoDevelop.Core; +using MonoDevelop.Ide.Editor; +using MonoDevelop.CodeIssues; +using Mono.Addins; +using ICSharpCode.NRefactory6.CSharp.Refactoring; +using MonoDevelop.Core.Text; +using System.Linq; + +namespace MonoDevelop.CodeActions +{ + static class CodeRefactoringService + { + readonly static List<CodeDiagnosticProvider> providers = new List<CodeDiagnosticProvider> (); + + static CodeRefactoringService () + { + providers.Add (new BuiltInCodeDiagnosticProvider ()); + + AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Refactoring/CodeDiagnosticProvider", delegate(object sender, ExtensionNodeEventArgs args) { + var node = (TypeExtensionNode)args.ExtensionNode; + switch (args.Change) { + case ExtensionChange.Add: + providers.Add ((CodeDiagnosticProvider)node.CreateInstance ()); + break; + } + }); + } + + public async static Task<IEnumerable<CodeDiagnosticDescriptor>> GetCodeDiagnosticsAsync (DocumentContext documentContext, string language, CancellationToken cancellationToken = default (CancellationToken)) + { + var result = new List<CodeDiagnosticDescriptor> (); + + foreach (var provider in providers) { + if (cancellationToken.IsCancellationRequested) + return Enumerable.Empty<CodeDiagnosticDescriptor> (); + result.AddRange (await provider.GetCodeDiagnosticDescriptorsAsync (documentContext, language, cancellationToken).ConfigureAwait (false)); + } + return result; + } + + public async static Task<IEnumerable<CodeDiagnosticFixDescriptor>> GetCodeFixesAsync (DocumentContext documentContext, string language, CancellationToken cancellationToken = default (CancellationToken)) + { + var result = new List<CodeDiagnosticFixDescriptor> (); + foreach (var provider in providers) { + result.AddRange (await provider.GetCodeFixDescriptorsAsync (documentContext, language, cancellationToken).ConfigureAwait (false)); + } + return result; + } + + public async static Task<IEnumerable<CodeRefactoringDescriptor>> GetCodeRefactoringsAsync (DocumentContext documentContext, string language, CancellationToken cancellationToken = default (CancellationToken)) + { + var result = new List<CodeRefactoringDescriptor> (); + foreach (var provider in providers) { + result.AddRange (await provider.GetCodeRefactoringDescriptorsAsync (documentContext, language, cancellationToken).ConfigureAwait (false)); + } + return result; + } + + public static async Task<IEnumerable<ValidCodeAction>> GetValidActionsAsync (TextEditor editor, DocumentContext doc, TextSpan span, CancellationToken cancellationToken = default (CancellationToken)) + { + if (editor == null) + throw new ArgumentNullException ("editor"); + if (doc == null) + throw new ArgumentNullException ("doc"); + var parsedDocument = doc.ParsedDocument; + var actions = new List<ValidCodeAction> (); + if (parsedDocument == null) + return actions; + var model = parsedDocument.GetAst<SemanticModel> (); + if (model == null) + return actions; + var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait (false); + if (span.End > root.Span.End) + return actions; + TextSpan tokenSegment = span; + var token = root.FindToken (span.Start); + if (!token.IsMissing) + tokenSegment = token.Span; + try { + foreach (var descriptor in await GetCodeRefactoringsAsync (doc, MimeTypeToLanguage(editor.MimeType), cancellationToken).ConfigureAwait (false)) { + if (cancellationToken.IsCancellationRequested) + return Enumerable.Empty<ValidCodeAction> (); + try { + await descriptor.GetProvider ().ComputeRefactoringsAsync ( + new CodeRefactoringContext (doc.AnalysisDocument, span, delegate (CodeAction ca) { + var nrca = ca as NRefactoryCodeAction; + var validSegment = tokenSegment; + if (nrca != null) + validSegment = nrca.TextSpan; + actions.Add (new ValidCodeAction (ca, validSegment)); + }, cancellationToken) + ).ConfigureAwait (false); + } catch (OperationCanceledException) { + if (cancellationToken.IsCancellationRequested) + return Enumerable.Empty<ValidCodeAction> (); + } catch (AggregateException) { + if (cancellationToken.IsCancellationRequested) + return Enumerable.Empty<ValidCodeAction> (); + } catch (Exception e) { + LoggingService.LogError ("Error while getting refactorings from " + descriptor.IdString, e); + continue; + } + } + } catch (OperationCanceledException) { + if (cancellationToken.IsCancellationRequested) + return Enumerable.Empty<ValidCodeAction> (); + } catch (AggregateException) { + if (cancellationToken.IsCancellationRequested) + return Enumerable.Empty<ValidCodeAction> (); + } + return actions; + } + + public static string MimeTypeToLanguage (string mimeType) + { + switch (mimeType) { + case "text/x-csharp": + return LanguageNames.CSharp; + } + return null; + } + } +} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/ICodeActionProviderSource.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/ValidCodeAction.cs index 155c74d767..803cd429be 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/ICodeActionProviderSource.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/ValidCodeAction.cs @@ -1,21 +1,21 @@ -// -// ICodeActionProviderSource.cs -// +// +// ValidCodeAction.cs +// // Author: // Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) -// +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -23,19 +23,25 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System.Collections.Generic; + +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Text; namespace MonoDevelop.CodeActions { /// <summary> - /// A code action provider source provides a way for language backends to add a set of generated code action providers. + /// Represents a code action that's valid at a specific segment. /// </summary> - public interface ICodeActionProviderSource + class ValidCodeAction { - /// <summary> - /// Gets the providers. - /// </summary> - IEnumerable<CodeActionProvider> GetProviders (); - } -} + public CodeAction CodeAction { get; private set; } + public TextSpan ValidSegment { get; private set; } + + public ValidCodeAction (CodeAction codeAction, TextSpan validSegment) + { + this.CodeAction = codeAction; + this.ValidSegment = validSegment; + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/ValidCodeDiagnosticAction.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/ValidCodeDiagnosticAction.cs new file mode 100644 index 0000000000..fb63ec19c8 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeActions/ValidCodeDiagnosticAction.cs @@ -0,0 +1,52 @@ +// +// ValidCodeDiagnosticAction.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using Microsoft.CodeAnalysis.CodeActions; +using MonoDevelop.Core.Text; +using MonoDevelop.CodeActions; +using Microsoft.CodeAnalysis; +using MonoDevelop.CodeIssues; +using Microsoft.CodeAnalysis.Text; + +namespace MonoDevelop.CodeActions +{ + /// <summary> + /// Represents a code action that's valid at a specific segment that was created as a action for a specific code diagnostic. + /// </summary> + class ValidCodeDiagnosticAction : ValidCodeAction + { + public CodeDiagnosticFixDescriptor Diagnostic { + get; + private set; + } + + public ValidCodeDiagnosticAction (CodeDiagnosticFixDescriptor diagnostic, CodeAction codeAction, TextSpan validSegment) : base (codeAction, validSegment) + { + this.Diagnostic = diagnostic; + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalyzersFromAssembly.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalyzersFromAssembly.cs new file mode 100644 index 0000000000..05331147ab --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalyzersFromAssembly.cs @@ -0,0 +1,106 @@ +// +// AnalyzersFromAssembly.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Threading; +using MonoDevelop.CodeIssues; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.CodeFixes; +using ICSharpCode.NRefactory6.CSharp.Refactoring; +using MonoDevelop.Core; +using System.Threading.Tasks; +using MonoDevelop.Ide.Editor; +using MonoDevelop.CodeActions; +using Microsoft.CodeAnalysis.CodeRefactorings; +using ICSharpCode.NRefactory6.CSharp; + +namespace MonoDevelop.CodeIssues +{ + + class AnalyzersFromAssembly + { + public List<CodeDiagnosticDescriptor> Analyzers; + public List<CodeDiagnosticFixDescriptor> Fixes; + public List<CodeRefactoringDescriptor> Refactorings; + + public readonly static AnalyzersFromAssembly Empty = new AnalyzersFromAssembly (); + + public AnalyzersFromAssembly () + { + Analyzers = new List<CodeDiagnosticDescriptor> (); + Fixes = new List<CodeDiagnosticFixDescriptor> (); + Refactorings = new List<CodeRefactoringDescriptor> (); + } + + internal static AnalyzersFromAssembly CreateFrom (System.Reflection.Assembly asm, bool force = false) + { + var result = new AnalyzersFromAssembly (); + result.AddAssembly (asm, force); + return result; + } + + internal void AddAssembly (System.Reflection.Assembly asm, bool force = false) + { + if (!force) { + var assemblyName = asm.GetName ().Name; + if (assemblyName == "MonoDevelop.AspNet" || + assemblyName == "Microsoft.CodeAnalysis.CSharp" || + assemblyName != "ICSharpCode.NRefactory6.CSharp.Refactoring" && + !(asm.GetReferencedAssemblies ().Any (a => a.Name == diagnosticAnalyzerAssembly) && asm.GetReferencedAssemblies ().Any (a => a.Name == "MonoDevelop.Ide"))) + return; + } + foreach (var type in asm.GetTypes ()) { + var analyzerAttr = (DiagnosticAnalyzerAttribute)type.GetCustomAttributes (typeof(DiagnosticAnalyzerAttribute), false).FirstOrDefault (); + if (analyzerAttr != null) { + var analyzer = (DiagnosticAnalyzer)Activator.CreateInstance (type); + foreach (var diag in analyzer.SupportedDiagnostics) { + try { + Analyzers.Add (new CodeDiagnosticDescriptor (diag, analyzerAttr.Languages, type)); + } catch (Exception e) { + LoggingService.LogError ("error while adding diagnostic analyzer: " + diag.Id + " from assembly " + asm.FullName, e); + } + } + } + + var codeFixAttr = (ExportCodeFixProviderAttribute)type.GetCustomAttributes (typeof(ExportCodeFixProviderAttribute), false).FirstOrDefault (); + if (codeFixAttr != null) { + Fixes.Add (new CodeDiagnosticFixDescriptor (type, codeFixAttr)); + } + + var exportAttr = type.GetCustomAttributes (typeof(ExportCodeRefactoringProviderAttribute), false).FirstOrDefault () as ExportCodeRefactoringProviderAttribute; + if (exportAttr != null) { + Refactorings.Add (new CodeRefactoringDescriptor (type, exportAttr)); + } + } + } + + readonly static string diagnosticAnalyzerAssembly = typeof (DiagnosticAnalyzerAttribute).Assembly.GetName ().Name; + + } + +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BuiltInCodeDiagnosticProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BuiltInCodeDiagnosticProvider.cs new file mode 100644 index 0000000000..bd00becc7c --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BuiltInCodeDiagnosticProvider.cs @@ -0,0 +1,111 @@ +// +// BuiltInCodeDiagnosticProvider.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Threading; +using MonoDevelop.CodeIssues; +using MonoDevelop.Core; +using System.Threading.Tasks; +using MonoDevelop.Ide.Editor; +using MonoDevelop.CodeActions; + +namespace MonoDevelop.CodeIssues +{ + + /// <summary> + /// Provides all IDE code diagnostics and fix provider. + /// (Scans the app domain for providers) + /// </summary> + class BuiltInCodeDiagnosticProvider : CodeDiagnosticProvider + { + readonly static Task<AnalyzersFromAssembly> builtInDiagnostics; + + static BuiltInCodeDiagnosticProvider () + { + builtInDiagnostics = Task.Run (() => { + var result = new AnalyzersFromAssembly (); + foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { + try { + result.AddAssembly (asm); + } catch (Exception e) { + LoggingService.LogError ("error while loading diagnostics in " + asm.FullName, e); + } + } + return result; + }); + } + + internal static CodeDiagnosticDescriptor GetCodeDiagnosticDescriptor (string diagnosticId) + { + foreach (var builtInDescriptor in BuiltInCodeDiagnosticProvider.GetBuiltInCodeDiagnosticDecsriptorsAsync (null).Result) { + if (builtInDescriptor.GetProvider ().SupportedDiagnostics.Any (diagnostic => diagnosticId == diagnostic.Id)) + return builtInDescriptor; + } + return null; + } + + internal async static Task<IEnumerable<CodeDiagnosticDescriptor>> GetBuiltInCodeDiagnosticDecsriptorsAsync (string language, bool includeDisabledNodes = false, CancellationToken cancellationToken = default (CancellationToken)) + { + builtInDiagnostics.Wait (cancellationToken); + var diags = await builtInDiagnostics; + var builtInCodeDiagnostics = diags.Analyzers; + if (string.IsNullOrEmpty (language)) + return includeDisabledNodes ? builtInCodeDiagnostics : builtInCodeDiagnostics.Where (act => act.IsEnabled); + return includeDisabledNodes ? builtInCodeDiagnostics.Where (ca => ca.Languages.Contains (language)) : builtInCodeDiagnostics.Where (ca => ca.Languages.Contains (language) && ca.IsEnabled); + } + + public async static Task<IEnumerable<CodeDiagnosticFixDescriptor>> GetBuiltInCodeFixDescriptorsAsync (string language, CancellationToken cancellationToken = default (CancellationToken)) + { + var diags = await builtInDiagnostics.ConfigureAwait (false); + var builtInCodeFixes = diags.Fixes; + return string.IsNullOrEmpty (language) ? builtInCodeFixes : builtInCodeFixes.Where (cfp => cfp.Languages.Contains (language)); + } + + public async static Task<IEnumerable<CodeRefactoringDescriptor>> GetBuiltInCodeRefactoringDescriptorsAsync (string language, bool includeDisabledNodes = false, CancellationToken cancellationToken = default (CancellationToken)) + { + var diags = await builtInDiagnostics.ConfigureAwait (false); + var builtInCodeFixes = diags.Refactorings; + return string.IsNullOrEmpty (language) ? builtInCodeFixes : builtInCodeFixes.Where (cfp => cfp.Language.Contains (language)); + } + + public override Task<IEnumerable<CodeDiagnosticFixDescriptor>> GetCodeFixDescriptorsAsync (DocumentContext document, string language, CancellationToken cancellationToken) + { + return GetBuiltInCodeFixDescriptorsAsync (language, cancellationToken); + } + + public override Task<IEnumerable<CodeDiagnosticDescriptor>> GetCodeDiagnosticDescriptorsAsync (DocumentContext document, string language, CancellationToken cancellationToken) + { + return GetBuiltInCodeDiagnosticDecsriptorsAsync (language, false, cancellationToken); + } + + public override Task<IEnumerable<CodeRefactoringDescriptor>> GetCodeRefactoringDescriptorsAsync (DocumentContext document, string language, CancellationToken cancellationToken = default (CancellationToken)) + { + return GetBuiltInCodeRefactoringDescriptorsAsync (language, false, cancellationToken); + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticDescriptor.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticDescriptor.cs new file mode 100644 index 0000000000..547c068621 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticDescriptor.cs @@ -0,0 +1,185 @@ +// +// CodeIssueDescriptor.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Microsoft.CodeAnalysis.Diagnostics; +using MonoDevelop.Core; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using MonoDevelop.Ide.Editor; +using ICSharpCode.NRefactory6.CSharp; + +namespace MonoDevelop.CodeIssues +{ + class CodeDiagnosticDescriptor + { + readonly Type diagnosticAnalyzerType; + readonly Microsoft.CodeAnalysis.DiagnosticDescriptor descriptor; + + DiagnosticAnalyzer instance; + + + /// <summary> + /// Gets the identifier string. + /// </summary> + internal string IdString { + get { + return diagnosticAnalyzerType.FullName; + } + } + + public Type DiagnosticAnalyzerType { + get { + return diagnosticAnalyzerType; + } + } + + /// <summary> + /// Gets the display name for this issue. + /// </summary> + public string Name { get; private set; } + + /// <summary> + /// Gets the description of the issue provider (used in the option panel). + /// </summary> + + /// <summary> + /// Gets the languages for this issue. + /// </summary> + public string[] Languages { get; private set; } + + public DiagnosticSeverity? DiagnosticSeverity { + get { + DiagnosticSeverity? result = null; + + foreach (var diagnostic in GetProvider ().SupportedDiagnostics) { + if (!result.HasValue) + result = GetSeverity(diagnostic); + if (result != GetSeverity(diagnostic)) + return null; + } + return result; + } + + set { + if (!value.HasValue) + return; + foreach (var diagnostic in GetProvider ().SupportedDiagnostics) { + SetSeverity (diagnostic, value.Value); + } + } + } + + /// <summary> + /// Gets or sets a value indicating whether this code action is enabled by the user. + /// </summary> + /// <value><c>true</c> if this code action is enabled; otherwise, <c>false</c>.</value> + public bool IsEnabled { + get { + foreach (var diagnostic in GetProvider ().SupportedDiagnostics) { + if (!GetIsEnabled (diagnostic)) + return false; + } + return true; + } + set { + foreach (var diagnostic in GetProvider ().SupportedDiagnostics) { + SetIsEnabled (diagnostic, value); + } + } + } + + internal DiagnosticSeverity GetSeverity (DiagnosticDescriptor diagnostic) + { + return PropertyService.Get ("CodeIssues." + Languages + "." + IdString + "." + diagnostic.Id + ".severity", diagnostic.DefaultSeverity); + } + + internal void SetSeverity (DiagnosticDescriptor diagnostic, DiagnosticSeverity severity) + { + PropertyService.Set ("CodeIssues." + Languages + "." + IdString + "." + diagnostic.Id + ".severity", severity); + } + + internal bool GetIsEnabled (DiagnosticDescriptor diagnostic) + { + return PropertyService.Get ("CodeIssues." + Languages + "." + IdString + "." + diagnostic.Id + ".enabled", true); + } + + internal void SetIsEnabled (DiagnosticDescriptor diagnostic, bool value) + { + PropertyService.Set ("CodeIssues." + Languages + "." + IdString + "." + diagnostic.Id + ".enabled", value); + } + + internal CodeDiagnosticDescriptor (Microsoft.CodeAnalysis.DiagnosticDescriptor descriptor, string[] languages, Type codeIssueType) + { + if (descriptor == null) + throw new ArgumentNullException ("descriptor"); + if (languages == null) + throw new ArgumentNullException ("languages"); + if (codeIssueType == null) + throw new ArgumentNullException ("codeIssueType"); + Name = descriptor.Title.ToString () ?? "unnamed"; + Languages = languages; + this.descriptor = descriptor; + this.diagnosticAnalyzerType = codeIssueType; + } + + /// <summary> + /// Gets the roslyn code action provider. + /// </summary> + public DiagnosticAnalyzer GetProvider () + { + if (instance == null) + instance = (DiagnosticAnalyzer)Activator.CreateInstance(diagnosticAnalyzerType); + + return instance; + } + + public override string ToString () + { + return string.Format ("[CodeIssueDescriptor: IdString={0}, Name={1}, Language={2}]", IdString, Name, Languages); + } + + public bool CanDisableWithPragma { get { return !string.IsNullOrEmpty (descriptor.Id); } } + + const string analysisDisableTag = "Analysis "; + + public void DisableWithPragma (TextEditor editor, DocumentContext context, TextSpan span) + { + using (editor.OpenUndoGroup ()) { + var start = editor.OffsetToLocation (span.Start); + var end = editor.OffsetToLocation (span.End); + editor.InsertText ( + editor.LocationToOffset (end.Line + 1, 1), + editor.GetVirtualIndentationString (end.Line) + "#pragma warning restore " + descriptor.Id + editor.EolMarker + ); + editor.InsertText ( + editor.LocationToOffset (start.Line, 1), + editor.GetVirtualIndentationString (start.Line) + "#pragma warning disable " + descriptor.Id + editor.EolMarker + ); + } + } + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticFixDescriptor.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticFixDescriptor.cs new file mode 100644 index 0000000000..7f26e14572 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticFixDescriptor.cs @@ -0,0 +1,89 @@ +// +// CodeFixDescriptor.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Diagnostics; +using System.Linq; +using MonoDevelop.Core; + +namespace MonoDevelop.CodeIssues +{ + class CodeDiagnosticFixDescriptor + { + readonly Type codeFixProviderType; + readonly ExportCodeFixProviderAttribute attribute; + CodeFixProvider instance; + + public string Name { + get { + return attribute.Name; + } + } + + public string[] Languages { + get { + return attribute.Languages; + } + } + + internal CodeDiagnosticFixDescriptor (Type codeFixProviderType, ExportCodeFixProviderAttribute attribute) + { + if (codeFixProviderType == null) + throw new ArgumentNullException ("codeFixProviderType"); + if (attribute == null) + throw new ArgumentNullException ("attribute"); + this.codeFixProviderType = codeFixProviderType; + this.attribute = attribute; + } + + public CodeFixProvider GetCodeFixProvider () + { + if (instance == null) { + try { + instance = (CodeFixProvider)Activator.CreateInstance (codeFixProviderType); + } catch (InvalidCastException e) { + LoggingService.LogError (codeFixProviderType + " can't be cast to CodeFixProvider."); + throw; + } + } + + return instance; + } + + public CodeDiagnosticDescriptor GetCodeDiagnosticDescriptor (string language) + { + var fixableIds = GetCodeFixProvider ().FixableDiagnosticIds.ToList (); + + foreach (var descriptor in BuiltInCodeDiagnosticProvider.GetBuiltInCodeDiagnosticDecsriptorsAsync (language).Result) { + if (descriptor.GetProvider ().SupportedDiagnostics.Any (diagnostic => fixableIds.Contains (diagnostic.Id))) + return descriptor; + + } + return null; + + } + } +} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedSymbolsHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticProvider.cs index 50c204a767..3cb3dd1da5 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedSymbolsHandler.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticProvider.cs @@ -1,10 +1,10 @@ // -// FindDerivedSymbolsHandler.cs +// CodeDiagnosticProvider.cs // // Author: // Mike Krüger <mkrueger@xamarin.com> // -// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com) +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,45 +23,23 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Ide.FindInFiles; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Analysis; -using MonoDevelop.Ide.TypeSystem; + using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using MonoDevelop.Projects; using System.Threading; -using MonoDevelop.Core; +using MonoDevelop.CodeIssues; +using System.Threading.Tasks; +using MonoDevelop.Ide.Editor; +using MonoDevelop.CodeActions; -namespace MonoDevelop.Refactoring +namespace MonoDevelop.CodeIssues { - class FindDerivedSymbolsHandler + /// <summary> + /// The code diagnostic provider gives a list of code diagnostic & fix providers from an arbitrary source. + /// </summary> + abstract class CodeDiagnosticProvider { - readonly IMember member; - - public FindDerivedSymbolsHandler (IMember member) - { - this.member = member; - } - - public bool IsValid { - get { - if (IdeApp.ProjectOperations.CurrentSelectedSolution == null) - return false; - if (TypeSystemService.GetProject (member) == null) - return false; - return member.IsVirtual || member.IsAbstract || member.DeclaringType.Kind == TypeKind.Interface; - } - } - - public void Run () - { - FindDerivedClassesHandler.FindDerivedMembers (member); - } + public abstract Task<IEnumerable<CodeDiagnosticDescriptor>> GetCodeDiagnosticDescriptorsAsync (DocumentContext document, string language, CancellationToken cancellationToken = default (CancellationToken)); + public abstract Task<IEnumerable<CodeDiagnosticFixDescriptor>> GetCodeFixDescriptorsAsync (DocumentContext document, string language, CancellationToken cancellationToken = default (CancellationToken)); + public abstract Task<IEnumerable<CodeRefactoringDescriptor>> GetCodeRefactoringDescriptorsAsync (DocumentContext document, string language, CancellationToken cancellationToken = default (CancellationToken)); } -} - +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticRunner.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticRunner.cs new file mode 100644 index 0000000000..233ae1fc6f --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeDiagnosticRunner.cs @@ -0,0 +1,108 @@ +// +// CodeAnalysisRunner.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +//#define PROFILE +using System; +using System.Linq; +using MonoDevelop.AnalysisCore; +using System.Collections.Generic; +using MonoDevelop.Ide.Gui; +using System.Threading; +using MonoDevelop.CodeIssues; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.CodeFixes; +using MonoDevelop.CodeActions; +using MonoDevelop.Core; +using MonoDevelop.AnalysisCore.Gui; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis; +using System.Threading.Tasks; + +namespace MonoDevelop.CodeIssues +{ + static class CodeDiagnosticRunner + { + public static IEnumerable<Result> Check (AnalysisDocument analysisDocument, CancellationToken cancellationToken) + { + var input = analysisDocument.DocumentContext; + if (!AnalysisOptions.EnableFancyFeatures || input.Project == null || !input.IsCompileableInProject || input.AnalysisDocument == null) + return Enumerable.Empty<Result> (); + try { + var model = input.ParsedDocument.GetAst<SemanticModel> (); + if (model == null) + return Enumerable.Empty<Result> (); + var compilation = model.Compilation; + var language = CodeRefactoringService.MimeTypeToLanguage (analysisDocument.Editor.MimeType); + + var providers = new List<DiagnosticAnalyzer> (); + var alreadyAdded = new HashSet<Type>(); + var diagnostics = CodeRefactoringService.GetCodeDiagnosticsAsync (analysisDocument.DocumentContext, language, cancellationToken); + foreach (var diagnostic in diagnostics.Result) { + if (alreadyAdded.Contains (diagnostic.DiagnosticAnalyzerType)) + continue; + alreadyAdded.Add (diagnostic.DiagnosticAnalyzerType); + var provider = diagnostic.GetProvider (); + providers.Add (provider); + } + if (providers.Count == 0 || cancellationToken.IsCancellationRequested) + return Enumerable.Empty<Result> (); + var localCompilation = CSharpCompilation.Create ( + compilation.AssemblyName, + new[] { model.SyntaxTree }, + compilation.References, + (CSharpCompilationOptions)compilation.Options + ); + + CompilationWithAnalyzers compilationWithAnalyzer; + try { + compilationWithAnalyzer = localCompilation.WithAnalyzers (System.Collections.Immutable.ImmutableArray<DiagnosticAnalyzer>.Empty.AddRange (providers), null, cancellationToken); + } catch (Exception) { + return Enumerable.Empty<Result> (); + } + + if (input.ParsedDocument == null || cancellationToken.IsCancellationRequested) + return Enumerable.Empty<Result> (); + var diagnosticList = new List<Diagnostic> (); + diagnosticList.AddRange (compilationWithAnalyzer.GetAnalyzerDiagnosticsAsync ().Result); + return diagnosticList + .Where (d => !d.Id.StartsWith("CS", StringComparison.Ordinal)) + .Select (diagnostic => { + var res = new DiagnosticResult(diagnostic); + // var line = analysisDocument.Editor.GetLineByOffset (res.Region.Start); + // Console.WriteLine (diagnostic.Id + "/" + res.Region +"/" + analysisDocument.Editor.GetTextAt (line)); + return res; + }); + } catch (OperationCanceledException) { + return Enumerable.Empty<Result> (); + } catch (AggregateException ae) { + ae.Flatten ().Handle (ix => ix is OperationCanceledException); + return Enumerable.Empty<Result> (); + } catch (Exception e) { + LoggingService.LogError ("Error while running diagnostics.", e); + return Enumerable.Empty<Result> (); + } + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssue.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssue.cs deleted file mode 100644 index 846f4dc678..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssue.cs +++ /dev/null @@ -1,108 +0,0 @@ -// -// CodeIssue.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using Mono.TextEditor; -using System.Collections.Generic; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.Refactoring; - -namespace MonoDevelop.CodeIssues -{ - /// <summary> - /// A code issue marks an issue inside a text editor. An issue is a description shown in the tooltip and - /// (optionally) a set of code actions to solve the issue. - /// </summary> - public class CodeIssue - { - /// <summary> - /// Gets or sets the description shown in the tooltip. - /// </summary> - public string Description { - get; - private set; - } - - /// <summary> - /// Gets or sets the region of the issue. - /// </summary> - public DomRegion Region { - get; - private set; - } - - - - /// <summary> - /// Gets or sets a value indicating how this issue should be marked inside the text editor. - /// Note: There is only one code issue provider generated therfore providers need to be state less. - /// </summary> - public IssueMarker IssueMarker { get; private set; } - - - /// <summary> - /// Gets or sets the code actions to solve the issue. - /// </summary> - public IEnumerable<MonoDevelop.CodeActions.CodeAction> Actions { - get; - private set; - } - - public string InspectorIdString { - get; - private set; - } - - /// <summary> - /// Gets or sets the code action providers for this issue. - /// </summary> - public IList<Type> ActionProvider { - get; - set; - } - - /// <summary> - /// Initializes a new instance of the <see cref="MonoDevelop.CodeIssues.CodeIssue"/> class. - /// </summary> - public CodeIssue (IssueMarker issueMarker, string description, string fileName, DocumentLocation start, DocumentLocation end, string inspectorIdString, IEnumerable<MonoDevelop.CodeActions.CodeAction> actions = null) : this (issueMarker, description, new DomRegion (fileName, start, end), inspectorIdString, actions) - { - } - - /// <summary> - /// Initializes a new instance of the <see cref="MonoDevelop.CodeIssues.CodeIssue"/> class. - /// </summary> - public CodeIssue (IssueMarker issueMarker, string description, DomRegion region, string inspectorIdString, IEnumerable<MonoDevelop.CodeActions.CodeAction> actions = null) - { - IssueMarker = issueMarker; - Description = description; - Region = region; - Actions = actions; - InspectorIdString = inspectorIdString; - } - - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssueAddinNode.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssueAddinNode.cs deleted file mode 100644 index d8aee4e498..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssueAddinNode.cs +++ /dev/null @@ -1,68 +0,0 @@ -// -// InspectorAddinNode.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using MonoDevelop.SourceEditor; -using Mono.Addins; -using MonoDevelop.Core; -using MonoDevelop.SourceEditor.QuickTasks; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.Refactoring; - -namespace MonoDevelop.CodeIssues -{ - public class CodeIssueAddinNode : TypeExtensionNode - { - [NodeAttribute ("mimeType", Required=true, Description="The mime type of this action.")] - string mimeType = null; - public string MimeType { - get { - return mimeType; - } - } - - [NodeAttribute ("severity", Required=true, Localizable=false, Description="The severity of this action.")] - Severity severity; - public Severity Severity { - get { - return severity; - } - } - - CodeIssueProvider inspector; - public CodeIssueProvider Inspector { - get { - if (inspector == null) { - inspector = (CodeIssueProvider)CreateInstance (); - inspector.DefaultSeverity = severity; - inspector.SetMimeType (MimeType); - } - return inspector; - } - } - - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssuePanelWidget.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssuePanelWidget.cs index 241f9281f6..b9d01f4337 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssuePanelWidget.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssuePanelWidget.cs @@ -28,14 +28,14 @@ using MonoDevelop.Ide.Gui.Dialogs; using Gtk; using MonoDevelop.Core; using System.Linq; -using MonoDevelop.SourceEditor; using MonoDevelop.Refactoring; using System.Collections.Generic; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Refactoring; using GLib; using MonoDevelop.Components; using Gdk; +using MonoDevelop.Ide.Editor; +using MonoDevelop.CodeActions; +using Microsoft.CodeAnalysis; using MonoDevelop.SourceEditor.QuickTasks; namespace MonoDevelop.CodeIssues @@ -73,19 +73,21 @@ namespace MonoDevelop.CodeIssues partial class CodeIssuePanelWidget : Bin { readonly string mimeType; - readonly TreeStore treeStore = new TreeStore (typeof(string), typeof(BaseCodeIssueProvider), typeof (string)); - readonly Dictionary<BaseCodeIssueProvider, Severity> severities = new Dictionary<BaseCodeIssueProvider, Severity> (); - readonly Dictionary<BaseCodeIssueProvider, bool> enableState = new Dictionary<BaseCodeIssueProvider, bool> (); + readonly TreeStore treeStore = new TreeStore (typeof(string), typeof(Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>), typeof (string)); + readonly Dictionary<Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>, DiagnosticSeverity?> severities = new Dictionary<Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>, DiagnosticSeverity?> (); + readonly Dictionary<Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>, bool> enableState = new Dictionary<Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>, bool> (); void GetAllSeverities () { - foreach (var node in RefactoringService.GetInspectors (mimeType)) { - severities [node] = node.GetSeverity (); - enableState [node] = node.GetIsEnabled (); - if (node.HasSubIssues) { - foreach (var subIssue in node.SubIssues) { - severities [subIssue] = subIssue.GetSeverity (); - enableState [subIssue] = subIssue.GetIsEnabled (); + foreach (var node in BuiltInCodeDiagnosticProvider.GetBuiltInCodeDiagnosticDecsriptorsAsync (CodeRefactoringService.MimeTypeToLanguage (mimeType), true).Result) { + var root = new Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor> (node, null); + severities [root] = node.DiagnosticSeverity; + enableState [root] = node.IsEnabled; + if (node.GetProvider ().SupportedDiagnostics.Length > 1) { + foreach (var subIssue in node.GetProvider ().SupportedDiagnostics) { + var sub = new Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor> (node, subIssue); + severities [sub] = node.GetSeverity (subIssue); + enableState [sub] = node.GetIsEnabled (subIssue); } } } @@ -102,8 +104,8 @@ namespace MonoDevelop.CodeIssues bool SelectCodeIssue (string idString, TreeIter iter) { do { - var provider = treeStore.GetValue (iter, 1) as BaseCodeIssueProvider; - if (provider != null && provider.IdString == idString) { + var provider = (Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>)treeStore.GetValue (iter, 1); + if (provider != null && idString == provider.Item1.IdString) { treeviewInspections.ExpandToPath (treeStore.GetPath (iter)); treeviewInspections.Selection.SelectIter (iter); return true; @@ -120,33 +122,30 @@ namespace MonoDevelop.CodeIssues return false; } - static string GetDescription (Severity severity) + static string GetDescription (DiagnosticSeverity severity) { switch (severity) { - case Severity.None: + case DiagnosticSeverity.Hidden: return GettextCatalog.GetString ("Do not show"); - case Severity.Error: + case DiagnosticSeverity.Error: return GettextCatalog.GetString ("Error"); - case Severity.Warning: + case DiagnosticSeverity.Warning: return GettextCatalog.GetString ("Warning"); - case Severity.Hint: - return GettextCatalog.GetString ("Hint"); - case Severity.Suggestion: - return GettextCatalog.GetString ("Suggestion"); + case DiagnosticSeverity.Info: + return GettextCatalog.GetString ("Info"); default: throw new ArgumentOutOfRangeException (); } } - Xwt.Drawing.Image GetIcon (Severity severity) + Xwt.Drawing.Image GetIcon (DiagnosticSeverity severity) { switch (severity) { - case Severity.Error: + case DiagnosticSeverity.Error: return QuickTaskOverviewMode.ErrorImage; - case Severity.Warning: + case DiagnosticSeverity.Warning: return QuickTaskOverviewMode.WarningImage; - case Severity.Hint: - case Severity.Suggestion: + case DiagnosticSeverity.Info: return QuickTaskOverviewMode.SuggestionImage; default: return QuickTaskOverviewMode.OkImage; @@ -157,25 +156,24 @@ namespace MonoDevelop.CodeIssues { categories.Clear (); treeStore.Clear (); - - var grouped = severities.Keys.OfType<CodeIssueProvider> () - .Where (node => string.IsNullOrEmpty (filter) || node.Title.IndexOf (filter, StringComparison.OrdinalIgnoreCase) > 0) - .GroupBy (node => node.Category) + var grouped = severities.Keys + .Where (node => node.Item2 == null && (string.IsNullOrEmpty (filter) || node.Item1.Name.IndexOf (filter, StringComparison.OrdinalIgnoreCase) > 0)) + .GroupBy (node => node.Item1.GetProvider ().SupportedDiagnostics.First ().Category) .OrderBy (g => g.Key, StringComparer.Ordinal); foreach (var g in grouped) { TreeIter categoryIter = treeStore.AppendValues ("<b>" + g.Key + "</b>", null, null); categories [g.Key] = categoryIter; - foreach (var node in g.OrderBy (n => n.Title, StringComparer.Ordinal)) { - var title = node.Title; + foreach (var node in g.OrderBy (n => n.Item1.Name, StringComparer.Ordinal)) { + var title = node.Item1.Name; MarkupSearchResult (filter, ref title); - var nodeIter = treeStore.AppendValues (categoryIter, title, node, node.Description); - if (node.HasSubIssues) { - foreach (var subIssue in node.SubIssues) { - title = subIssue.Title; + var nodeIter = treeStore.AppendValues (categoryIter, title, node, node.Item1.Name); + if (node.Item1.GetProvider ().SupportedDiagnostics.Length > 1) { + foreach (var subIssue in node.Item1.GetProvider ().SupportedDiagnostics) { + title = subIssue.Description.ToString (); MarkupSearchResult (filter, ref title); - treeStore.AppendValues (nodeIter, title, subIssue, subIssue.Description); + treeStore.AppendValues (nodeIter, title, new Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor> (node.Item1, subIssue), subIssue.Description); } } } @@ -241,7 +239,7 @@ namespace MonoDevelop.CodeIssues toggleRenderer.Toggled += delegate(object o, ToggledArgs args) { TreeIter iter; if (treeStore.GetIterFromString (out iter, args.Path)) { - var provider = (BaseCodeIssueProvider)treeStore.GetValue (iter, 1); + var provider = (Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>)treeStore.GetValue (iter, 1); enableState[provider] = !enableState[provider]; } }; @@ -251,7 +249,7 @@ namespace MonoDevelop.CodeIssues titleCol.PackStart (toggleRenderer, false); titleCol.Sizing = TreeViewColumnSizing.Autosize; titleCol.SetCellDataFunc (toggleRenderer, delegate (TreeViewColumn treeColumn, CellRenderer cell, TreeModel model, TreeIter iter) { - var provider = (BaseCodeIssueProvider)model.GetValue (iter, 1); + var provider = (Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>)treeStore.GetValue (iter, 1); if (provider == null) { toggleRenderer.Visible = false; return; @@ -284,12 +282,11 @@ namespace MonoDevelop.CodeIssues col.MinWidth = 100; col.Expand = false; - var comboBoxStore = new ListStore (typeof(string), typeof(Severity)); + var comboBoxStore = new ListStore (typeof(string), typeof(DiagnosticSeverity)); // comboBoxStore.AppendValues (GetDescription (Severity.None), Severity.None); - comboBoxStore.AppendValues (GetDescription (Severity.Error), Severity.Error); - comboBoxStore.AppendValues (GetDescription (Severity.Warning), Severity.Warning); - comboBoxStore.AppendValues (GetDescription (Severity.Hint), Severity.Hint); - comboBoxStore.AppendValues (GetDescription (Severity.Suggestion), Severity.Suggestion); + comboBoxStore.AppendValues (GetDescription (DiagnosticSeverity.Error), DiagnosticSeverity.Error); + comboBoxStore.AppendValues (GetDescription (DiagnosticSeverity.Warning), DiagnosticSeverity.Warning); + comboBoxStore.AppendValues (GetDescription (DiagnosticSeverity.Info), DiagnosticSeverity.Info); comboRenderer.Model = comboBoxStore; comboRenderer.Mode = CellRendererMode.Activatable; comboRenderer.TextColumn = 0; @@ -307,8 +304,8 @@ namespace MonoDevelop.CodeIssues return; do { if ((string)comboBoxStore.GetValue (storeIter, 0) == args.NewText) { - var provider = (BaseCodeIssueProvider)treeStore.GetValue (iter, 1); - var severity = (Severity)comboBoxStore.GetValue (storeIter, 1); + var provider = (Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>)treeStore.GetValue (iter, 1); + var severity = (DiagnosticSeverity)comboBoxStore.GetValue (storeIter, 1); severities[provider] = severity; return; } @@ -316,15 +313,19 @@ namespace MonoDevelop.CodeIssues }; col.SetCellDataFunc (comboRenderer, delegate (TreeViewColumn treeColumn, CellRenderer cell, TreeModel model, TreeIter iter) { - var provider = (BaseCodeIssueProvider)model.GetValue (iter, 1); + var provider = (Tuple<CodeDiagnosticDescriptor, DiagnosticDescriptor>)treeStore.GetValue (iter, 1); if (provider == null) { comboRenderer.Visible = false; return; } var severity = severities[provider]; + if (!severity.HasValue) { + comboRenderer.Visible = false; + return; + } comboRenderer.Visible = true; - comboRenderer.Text = GetDescription (severity); - comboRenderer.Icon = GetIcon (severity); + comboRenderer.Text = GetDescription (severity.Value); + comboRenderer.Icon = GetIcon (severity.Value); }); treeviewInspections.HeadersVisible = false; treeviewInspections.Model = treeStore; @@ -342,10 +343,25 @@ namespace MonoDevelop.CodeIssues public void ApplyChanges () { - foreach (var kv in severities) - kv.Key.SetSeverity (kv.Value); - foreach (var kv in enableState) - kv.Key.SetIsEnabled (kv.Value); + foreach (var kv in severities) { + var userSeverity = kv.Value; + if (!userSeverity.HasValue) + continue; + if (kv.Key.Item2 == null) { + kv.Key.Item1.DiagnosticSeverity = userSeverity; + continue; + } + kv.Key.Item1.SetSeverity (kv.Key.Item2, userSeverity.Value); + } + + foreach (var kv in enableState) { + var userIsEnabled = kv.Value; + if (kv.Key.Item2 == null) { + kv.Key.Item1.IsEnabled = userIsEnabled; + continue; + } + kv.Key.Item1.SetIsEnabled (kv.Key.Item2, userIsEnabled); + } } } -}
\ No newline at end of file +} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssueProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssueProvider.cs deleted file mode 100644 index d9a2abe2ef..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssueProvider.cs +++ /dev/null @@ -1,207 +0,0 @@ -// -// IInspector.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin <http://xamarin.com> -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System.Collections.Generic; -using System.Threading; -using MonoDevelop.Core; -using ICSharpCode.NRefactory.Refactoring; -using Mono.TextEditor; -using System; - -namespace MonoDevelop.CodeIssues -{ - public abstract class BaseCodeIssueProvider - { - public virtual CodeIssueProvider Parent { - get { - return null; - } - } - /// <summary> - /// Gets or sets the type of the MIME the provider is attached to. - /// </summary> - public abstract string MimeType { - get; - } - - /// <summary> - /// Gets or sets the title of the issue provider (used in the option panel). - /// </summary> - public string Title { get; set; } - - /// <summary> - /// Gets or sets the description of the issue provider (used in the option panel). - /// </summary> - public string Description { get; set; } - - - /// <summary> - /// Gets the identifier string used as property ID tag. - /// </summary> - public virtual string IdString { - get { - return "refactoring.codeissues." + MimeType + "." + GetType ().FullName; - } - } - - /// <summary> - /// Gets or sets the default severity. Note that GetSeverity () should be called to get the valid value inside the IDE. - /// </summary> - public Severity DefaultSeverity { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this issue is enabled. Note that GetIsEnabled () should be called to get the valid value inside the IDE. - /// </summary> - /// <value><c>true</c> if this instance is enabled; otherwise, <c>false</c>.</value> - public bool IsEnabledByDefault { get; set; } - - /// <summary> - /// Gets the current (user defined) severity. - /// </summary> - protected Severity severity; - - public Severity GetSeverity () - { - return severity; - } - - /// <summary> - /// Sets the user defined severity. - /// </summary> - public void SetSeverity (Severity severity) - { - if (this.severity == severity) - return; - this.severity = severity; - PropertyService.Set (IdString, severity); - } - - - protected bool isEnabled; - - public bool GetIsEnabled () - { - return isEnabled; - } - - /// <summary> - /// Sets the user defined severity. - /// </summary> - public void SetIsEnabled (bool isEnabled) - { - if (this.isEnabled == isEnabled) - return; - this.isEnabled = isEnabled; - PropertyService.Set (IdString + ".isEnabled", isEnabled); - } - - protected void UpdateSeverity () - { - severity = PropertyService.Get<Severity> (IdString, DefaultSeverity); - isEnabled = PropertyService.Get<bool> (IdString+ ".isEnabled", IsEnabledByDefault); - } - - /// <summary> - /// Gets all the code issues inside a document. - /// </summary> - public abstract IEnumerable<CodeIssue> GetIssues (object refactoringContext, CancellationToken cancellationToken); - - public virtual bool CanDisableOnce { get { return false; } } - - public virtual bool CanDisableAndRestore { get { return false; } } - - public virtual bool CanDisableWithPragma { get { return false; } } - - public virtual bool CanSuppressWithAttribute { get { return false; } } - - public virtual void DisableOnce (MonoDevelop.Ide.Gui.Document document, DocumentRegion loc) - { - throw new NotSupportedException (); - } - - public virtual void DisableAndRestore (MonoDevelop.Ide.Gui.Document document, DocumentRegion loc) - { - throw new NotSupportedException (); - } - - public virtual void DisableWithPragma (MonoDevelop.Ide.Gui.Document document, DocumentRegion loc) - { - throw new NotSupportedException (); - } - - public virtual void SuppressWithAttribute (MonoDevelop.Ide.Gui.Document document, DocumentRegion loc) - { - throw new NotSupportedException (); - } - } - - - /// <summary> - /// A code issue provider is a factory that creates code issues of a given document. - /// </summary> - public abstract class CodeIssueProvider : BaseCodeIssueProvider - { - string mimeType; - public override string MimeType { - get { - return mimeType; - } - } - - public void SetMimeType (string mimeType) - { - this.mimeType = mimeType; - UpdateSeverity (); - } - - /// <summary> - /// Gets or sets the category of the issue provider (used in the option panel). - /// </summary> - public string Category { get; set; } - - /// <summary> - /// If true this issue has sub issues. - /// </summary> - public abstract bool HasSubIssues { get; } - - /// <summary> - /// Gets the sub issues of this issue. If HasSubIssus == false an InvalidOperationException is thrown. - /// </summary> - public virtual IEnumerable<BaseCodeIssueProvider> SubIssues { get { throw new InvalidOperationException (); } } - - /// <summary> - /// Gets the effective set of providers. The effective set of providers - /// is either the sub issues (if it has sub issues) or simply itself (otherwise). - /// </summary> - /// <returns>The effective provider set.</returns> - public IEnumerable<BaseCodeIssueProvider> GetEffectiveProviderSet() - { - if (HasSubIssues) - return SubIssues; - return new[] { this }; - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/DefaultCodeIssueCategories.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/DefaultCodeIssueCategories.cs deleted file mode 100644 index 68f473ed32..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/DefaultCodeIssueCategories.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// DefaultInspectionCategories.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin <http://xamarin.com> -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using MonoDevelop.Core; - -namespace MonoDevelop.CodeIssues -{ - /// <summary> - /// Default code issue categories provide strings to common categories used in the code issue options panel. - /// </summary> - public static class DefaultCodeIssueCategories - { - public readonly static string Improvements = GettextCatalog.GetString ("Code Improvements"); - public readonly static string CodeQualityIssues = GettextCatalog.GetString ("Code Quality Issues"); - public readonly static string ConstraintViolations = GettextCatalog.GetString ("Constraint Violations"); - public readonly static string Redundancies = GettextCatalog.GetString ("Redundancies"); - public readonly static string Opportunities = GettextCatalog.GetString ("Language Usage Opportunities"); - public readonly static string Notifications = GettextCatalog.GetString ("Code Notifications"); - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/DiagnosticResult.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/DiagnosticResult.cs new file mode 100644 index 0000000000..f14a822101 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/DiagnosticResult.cs @@ -0,0 +1,77 @@ +// +// CodeAnalysisRunner.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +//#define PROFILE +using System; +using MonoDevelop.AnalysisCore; +using ICSharpCode.NRefactory6.CSharp; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis; + +namespace MonoDevelop.CodeIssues +{ + class DiagnosticResult : Result + { + readonly Diagnostic diagnostic; + + public Diagnostic Diagnostic { + get { + return diagnostic; + } + } + + public DiagnosticResult (Diagnostic diagnostic) : base (GetSpan (diagnostic), diagnostic.GetMessage ()) + { + if (diagnostic == null) + throw new ArgumentNullException ("diagnostic"); + this.diagnostic = diagnostic; + + SetSeverity (diagnostic.Severity, GetIssueMarker ()); + } + + static TextSpan GetSpan (Diagnostic diagnostic) + { + int start = diagnostic.Location.SourceSpan.Start; + int end = diagnostic.Location.SourceSpan.End; + + foreach (var loc in diagnostic.AdditionalLocations) { + start = Math.Min (start, loc.SourceSpan.Start); + end = Math.Max (start, loc.SourceSpan.End); + } + + return TextSpan.FromBounds (start, end); + } + + IssueMarker GetIssueMarker () + { + if (diagnostic.Descriptor.Category == DiagnosticAnalyzerCategories.RedundanciesInCode || diagnostic.Descriptor.Category == DiagnosticAnalyzerCategories.RedundanciesInDeclarations) + return IssueMarker.GrayOut; + if (diagnostic.Severity == DiagnosticSeverity.Info) + return IssueMarker.DottedLine; + return IssueMarker.WavedLine; + } + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AbstractGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/AbstractGroupingProvider.cs index 3f7cd390c7..3f7cd390c7 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AbstractGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/AbstractGroupingProvider.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ActionSummary.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ActionSummary.cs index 42eda56ce6..7a560e69fd 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ActionSummary.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ActionSummary.cs @@ -23,11 +23,10 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using Mono.TextEditor; +using MonoDevelop.Ide.Editor; namespace MonoDevelop.CodeIssues { - public class ActionSummary { /// <summary> diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisState.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/AnalysisState.cs index 221e11d819..221e11d819 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisState.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/AnalysisState.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisStateChangeEventArgs.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/AnalysisStateChangeEventArgs.cs index 7531189f08..7531189f08 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisStateChangeEventArgs.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/AnalysisStateChangeEventArgs.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BatchFixer.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/BatchFixer.cs index a0d4cf4cde..c4c6491f05 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/BatchFixer.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/BatchFixer.cs @@ -36,9 +36,9 @@ using System.Threading; using MonoDevelop.Projects; using MonoDevelop.Ide.TypeSystem; using ICSharpCode.NRefactory.CSharp; -using Mono.TextEditor.Utils; using System.Text; -using Mono.TextEditor; +using MonoDevelop.Ide.Editor; +using MonoDevelop.Core.Text; namespace MonoDevelop.CodeIssues { @@ -77,10 +77,8 @@ namespace MonoDevelop.CodeIssues var fileSummaries = issueSummaries.Where (summary => summary.File == file); var inspectorIds = new HashSet<string> (fileSummaries.Select (summary => summary.InspectorIdString)); - bool hadBom; - Encoding encoding; bool isOpen; - var data = TextFileProvider.Instance.GetTextEditorData (file.FilePath, out hadBom, out encoding, out isOpen); + var data = TextFileProvider.Instance.GetTextEditorData (file.FilePath, out isOpen); IRefactoringContext refactoringContext; var realActions = GetIssues (data, file, inspectorIds, out refactoringContext).SelectMany (issue => issue.Actions).ToList (); if (realActions.Count == 0 || refactoringContext == null) @@ -94,44 +92,44 @@ namespace MonoDevelop.CodeIssues if (!isOpen) { // If the file is open we leave it to the user to explicitly save the file - TextFileUtility.WriteText (file.Name, data.Text, encoding, hadBom); + data.Save (); } }); return appliedActions; } - static IList<CodeIssue> GetIssues (TextEditorData data, ProjectFile file, ISet<string> inspectorIds, out IRefactoringContext refactoringContext) + static IList<CodeIssue> GetIssues (ITextDocument data, ProjectFile file, ISet<string> inspectorIds, out IRefactoringContext refactoringContext) { var issues = new List<CodeIssue> (); - - var document = TypeSystemService.ParseFile (file.Project, data); - if (document == null) { +// +// var document = TypeSystemService.ParseFile (file.Project, data); +// if (document == null) { refactoringContext = null; - return issues; - } - - var content = TypeSystemService.GetProjectContext (file.Project); - var compilation = content.AddOrUpdateFiles (document.ParsedFile).CreateCompilation (); - var resolver = new CSharpAstResolver (compilation, document.GetAst<SyntaxTree> (), document.ParsedFile as ICSharpCode.NRefactory.CSharp.TypeSystem.CSharpUnresolvedFile); - - refactoringContext = document.CreateRefactoringContextWithEditor (data, resolver, CancellationToken.None); - var context = refactoringContext; - foreach (var provider in GetInspectors (data, inspectorIds)) { - var severity = provider.GetSeverity (); - if (severity == Severity.None || !provider.GetIsEnabled ()) - continue; - try { - lock (issues) { - issues.AddRange (provider.GetIssues (context, CancellationToken.None)); - } - } catch (Exception ex) { - LoggingService.LogError ("Error while running code issue on: " + data.FileName, ex); - } - } +// return issues; +// } +// +// var content = TypeSystemService.GetProjectContext (file.Project); +// var compilation = content.AddOrUpdateFiles (document.ParsedFile).CreateCompilation (); +// var resolver = new CSharpAstResolver (compilation, document.GetAst<SyntaxTree> (), document.ParsedFile as ICSharpCode.NRefactory.CSharp.TypeSystem.CSharpUnresolvedFile); +// +// refactoringContext = document.CreateRefactoringContextWithEditor (data, resolver, CancellationToken.None); +// var context = refactoringContext; +// foreach (var provider in GetInspectors (data, inspectorIds)) { +// var severity = provider.GetSeverity (); +// if (severity == Severity.None || !provider.GetIsEnabled ()) +// continue; +// try { +// lock (issues) { +// issues.AddRange (provider.GetIssues (context, CancellationToken.None)); +// } +// } catch (Exception ex) { +// LoggingService.LogError ("Error while running code issue on: " + data.FileName, ex); +// } +// } return issues; } - static IList<CodeIssueProvider> GetInspectors (TextEditorData editor, ICollection<string> inspectorIds) + static IList<CodeIssueProvider> GetInspectors (IReadonlyTextDocument editor, ICollection<string> inspectorIds) { var inspectors = RefactoringService.GetInspectors (editor.MimeType).ToList (); return inspectors diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CategoryGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/CategoryGroupingProvider.cs index bb7094f20d..bb7094f20d 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CategoryGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/CategoryGroupingProvider.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeAnalysisBatchRunner.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/CodeAnalysisBatchRunner.cs index 8463822b85..a2e9b91a5e 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeAnalysisBatchRunner.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/CodeAnalysisBatchRunner.cs @@ -39,125 +39,125 @@ using ICSharpCode.NRefactory.Refactoring; using MonoDevelop.Core; using System.Collections.Concurrent; using ICSharpCode.NRefactory.TypeSystem; -using Mono.TextEditor; using MonoDevelop.Core.Instrumentation; using MonoDevelop.Refactoring; using System.Collections.Generic; -using MonoDevelop.Core;
-
-namespace MonoDevelop.CodeIssues
-{
- public class CodeAnalysisBatchRunner
- {
- private readonly object _lock = new object ();
-
- private int workerCount;
-
- private readonly AnalysisJobQueue jobQueue = new AnalysisJobQueue ();
-
- public IJobContext QueueJob (IAnalysisJob job)
- {
- jobQueue.Add (job);
- EnsureRunning ();
- return new JobContext (job, jobQueue, this);
- }
-
- private void EnsureRunning ()
- {
- for (; Interlocked.Add (ref workerCount, 1) < Environment.ProcessorCount;) {
- new Thread (() => {
- try {
- ProcessQueue ();
- }
- finally {
- Interlocked.Add (ref workerCount, -1);
- }
- }).Start ();
- }
- }
-
- private void ProcessQueue ()
- {
- while (true) {
- try {
- using (var slice = GetSlice ()) {
- if (slice == null)
- // TODO: Do something smarter if the queue is empty
- return;
- AnalyzeFile (slice, slice.GetJobs ().SelectMany (job => job.GetIssueProviders (slice.File)));
- }
- } catch (Exception e) {
- LoggingService.LogInternalError (e);
- }
- }
- }
-
- private JobSlice GetSlice ()
- {
- lock (_lock) {
- return jobQueue.Dequeue (1).FirstOrDefault ();
- }
- }
-
- void AnalyzeFile (JobSlice item, IEnumerable<BaseCodeIssueProvider> codeIssueProviders) - { - var file = item.File; +using MonoDevelop.Core; - if (file.BuildAction != BuildAction.Compile) - return; +namespace MonoDevelop.CodeIssues +{ + public class CodeAnalysisBatchRunner + { + private readonly object _lock = new object (); - if (!(file.Project is DotNetProject)) - return; + private int workerCount; - TextEditorData editor; - try { - editor = TextFileProvider.Instance.GetReadOnlyTextEditorData (file.FilePath); - } catch (FileNotFoundException) { - // Swallow exception and ignore this file - return; - } - var document = TypeSystemService.ParseFile (file.Project, editor); - if (document == null) - return; + private readonly AnalysisJobQueue jobQueue = new AnalysisJobQueue (); - var content = TypeSystemService.GetProjectContext (file.Project); - var compilation = content.AddOrUpdateFiles (document.ParsedFile).CreateCompilation (); + public IJobContext QueueJob (IAnalysisJob job) + { + jobQueue.Add (job); + EnsureRunning (); + return new JobContext (job, jobQueue, this); + } - CSharpAstResolver resolver; - using (var timer = ExtensionMethods.ResolveCounter.BeginTiming ()) { - resolver = new CSharpAstResolver (compilation, document.GetAst<SyntaxTree> (), document.ParsedFile as ICSharpCode.NRefactory.CSharp.TypeSystem.CSharpUnresolvedFile); - try { - resolver.ApplyNavigator (new ExtensionMethods.ConstantModeResolveVisitorNavigator (ResolveVisitorNavigationMode.Resolve, null)); - } catch (Exception e) { - LoggingService.LogError ("Error while applying navigator", e); - } + private void EnsureRunning () + { + for (; Interlocked.Add (ref workerCount, 1) < Environment.ProcessorCount;) { + new Thread (() => { + try { + ProcessQueue (); + } + finally { + Interlocked.Add (ref workerCount, -1); + } + }).Start (); } - var context = document.CreateRefactoringContextWithEditor (editor, resolver, CancellationToken.None); + } - foreach (var provider in codeIssueProviders) { - if (item.CancellationToken.IsCancellationRequested) - break; - IList<IAnalysisJob> jobs; - lock (_lock) - jobs = item.GetJobs ().ToList (); - var jobsForProvider = jobs.Where (j => j.GetIssueProviders (file).Contains (provider)).ToList(); + private void ProcessQueue () + { + while (true) { try { - var issues = provider.GetIssues (context, CancellationToken.None).ToList (); - foreach (var job in jobsForProvider) { - // Call AddResult even if issues.Count == 0, to enable a job implementation to keep - // track of progress information. - job.AddResult (file, provider, issues); + using (var slice = GetSlice ()) { + if (slice == null) + // TODO: Do something smarter if the queue is empty + return; + AnalyzeFile (slice, slice.GetJobs ().SelectMany (job => job.GetIssueProviders (slice.File))); } - } catch (OperationCanceledException) { - // The operation was cancelled, no-op as the user-visible parts are - // handled elsewhere } catch (Exception e) { - foreach (var job in jobsForProvider) { - job.AddError (file, provider); - } + LoggingService.LogError ("Unhandled exception", e); + MessageService.ShowException (e); } } } + + private JobSlice GetSlice () + { + lock (_lock) { + return jobQueue.Dequeue (1).FirstOrDefault (); + } + } + + void AnalyzeFile (JobSlice item, IEnumerable<BaseCodeIssueProvider> codeIssueProviders) + { +// var file = item.File; +// +// if (file.BuildAction != BuildAction.Compile) +// return; +// +// if (!(file.Project is DotNetProject)) +// return; +// +// TextEditorData editor; +// try { +// editor = TextFileProvider.Instance.GetReadOnlyTextEditorData (file.FilePath); +// } catch (FileNotFoundException) { +// // Swallow exception and ignore this file +// return; +// } +// var document = TypeSystemService.ParseFile (file.Project, editor); +// if (document == null) +// return; +// +// var content = TypeSystemService.GetProjectContext (file.Project); +// var compilation = content.AddOrUpdateFiles (document.ParsedFile).CreateCompilation (); +// +// CSharpAstResolver resolver; +// using (var timer = ExtensionMethods.ResolveCounter.BeginTiming ()) { +// resolver = new CSharpAstResolver (compilation, document.GetAst<SyntaxTree> (), document.ParsedFile as ICSharpCode.NRefactory.CSharp.TypeSystem.CSharpUnresolvedFile); +// try { +// resolver.ApplyNavigator (new ExtensionMethods.ConstantModeResolveVisitorNavigator (ResolveVisitorNavigationMode.Resolve, null)); +// } catch (Exception e) { +// LoggingService.LogError ("Error while applying navigator", e); +// } +// } +// var context = document.CreateRefactoringContextWithEditor (editor, resolver, CancellationToken.None); +// +// foreach (var provider in codeIssueProviders) { +// if (item.CancellationToken.IsCancellationRequested) +// break; +// IList<IAnalysisJob> jobs; +// lock (_lock) +// jobs = item.GetJobs ().ToList (); +// var jobsForProvider = jobs.Where (j => j.GetIssueProviders (file).Contains (provider)).ToList(); +// try { +// var issues = provider.GetIssues (context, CancellationToken.None).ToList (); +// foreach (var job in jobsForProvider) { +// // Call AddResult even if issues.Count == 0, to enable a job implementation to keep +// // track of progress information. +// job.AddResult (file, provider, issues); +// } +// } catch (OperationCanceledException) { +// // The operation was cancelled, no-op as the user-visible parts are +// // handled elsewhere +// } catch (Exception e) { +// foreach (var job in jobsForProvider) { +// job.AddError (file, provider); +// } +// } +// } + } } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssuePad.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/CodeIssuePad.cs index c875894512..c875894512 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeIssuePad.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/CodeIssuePad.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ExactIssueMatcher.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ExactIssueMatcher.cs index 3f1db8df72..3f1db8df72 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ExactIssueMatcher.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ExactIssueMatcher.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/FileGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/FileGroupingProvider.cs index a92561d2d6..aa1d64d7cf 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/FileGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/FileGroupingProvider.cs @@ -1,46 +1,46 @@ -//
-// FileGroupingProvider.cs
-//
-// Author:
-// Marius Ungureanu <marius.ungureanu@xamarin.com>
-//
-// Copyright (c) 2013 Marius Ungureanu
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using MonoDevelop.Projects;
-using MonoDevelop.Core;
-
-namespace MonoDevelop.CodeIssues
-{
- [GroupingDescription("File")]
- public class FileGroupingProvider : AbstractGroupingProvider<ProjectFile>
- {
- #region implemented abstract members of AbstractGroupingProvider
- protected override ProjectFile GetGroupingKey (IssueSummary issue)
- {
- return issue.File;
- }
- protected override string GetGroupName (IssueSummary issue)
- {
- return issue.File.FilePath.ToRelative (issue.Project.BaseDirectory);
- }
- #endregion
- }
-}
-
+// +// FileGroupingProvider.cs +// +// Author: +// Marius Ungureanu <marius.ungureanu@xamarin.com> +// +// Copyright (c) 2013 Marius Ungureanu +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using MonoDevelop.Projects; +using MonoDevelop.Core; + +namespace MonoDevelop.CodeIssues +{ + [GroupingDescription("File")] + public class FileGroupingProvider : AbstractGroupingProvider<ProjectFile> + { + #region implemented abstract members of AbstractGroupingProvider + protected override ProjectFile GetGroupingKey (IssueSummary issue) + { + return issue.File; + } + protected override string GetGroupName (IssueSummary issue) + { + return issue.File.FilePath.ToRelative (issue.Project.BaseDirectory); + } + #endregion + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/GroupingDescriptionAttribute.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/GroupingDescriptionAttribute.cs index 720084149e..720084149e 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/GroupingDescriptionAttribute.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/GroupingDescriptionAttribute.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/GroupingProviderChainControl.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/GroupingProviderChainControl.cs index 3449d7b24b..3449d7b24b 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/GroupingProviderChainControl.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/GroupingProviderChainControl.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/GroupingProviderEventArgs.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/GroupingProviderEventArgs.cs index f9eee0fc87..f9eee0fc87 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/GroupingProviderEventArgs.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/GroupingProviderEventArgs.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IActionMatcher.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IActionMatcher.cs index 8e732f596a..8e732f596a 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IActionMatcher.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IActionMatcher.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IGroupingProvider.cs index 19b0001bf4..19b0001bf4 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IGroupingProvider.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IIssueSummarySink.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IIssueSummarySink.cs index af1cb51c0c..af1cb51c0c 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IIssueSummarySink.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IIssueSummarySink.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IIssueTreeNode.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IIssueTreeNode.cs index 68cf43ef50..68cf43ef50 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IIssueTreeNode.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IIssueTreeNode.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueGroup.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueGroup.cs index 10e261b7fc..10e261b7fc 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueGroup.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueGroup.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueGroupEventArgs.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueGroupEventArgs.cs index 42787d4560..42787d4560 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueGroupEventArgs.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueGroupEventArgs.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueMatch.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueMatch.cs index fbdaafcd57..fbdaafcd57 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueMatch.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueMatch.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueSummary.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueSummary.cs index bb022e92a8..5e7c4d201c 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueSummary.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueSummary.cs @@ -53,10 +53,10 @@ namespace MonoDevelop.CodeIssues InspectorIdString = codeIssue.InspectorIdString }; issueSummary.Actions = codeIssue.Actions.Select (a => new ActionSummary { - Batchable = a.SupportsBatchRunning, - SiblingKey = a.SiblingKey, - Title = a.Title, - Region = a.DocumentRegion, +// Batchable = a.SupportsBatchRunning, +// SiblingKey = a.SiblingKey, +// Title = a., +// Region = a.DocumentRegion, IssueSummary = issueSummary }).ToList (); return issueSummary; diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueTreeNodeEventArgs.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueTreeNodeEventArgs.cs index 37d663f252..37d663f252 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/IssueTreeNodeEventArgs.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/IssueTreeNodeEventArgs.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/NullGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/NullGroupingProvider.cs index 677d9989c6..677d9989c6 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/NullGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/NullGroupingProvider.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ProjectGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ProjectGroupingProvider.cs index 7ca19ba063..7ca19ba063 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ProjectGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ProjectGroupingProvider.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ProviderGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ProviderGroupingProvider.cs index 7cdf46e461..7cdf46e461 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/ProviderGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/ProviderGroupingProvider.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/AnalysisJobQueue.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/AnalysisJobQueue.cs index cdb3182fbb..cdb3182fbb 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/AnalysisJobQueue.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/AnalysisJobQueue.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/CodeIssueEventArgs.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/CodeIssueEventArgs.cs index 53e3a29f8b..53e3a29f8b 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/CodeIssueEventArgs.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/CodeIssueEventArgs.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/IAnalysisJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IAnalysisJob.cs index 0ab2553b4f..0ab2553b4f 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/IAnalysisJob.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IAnalysisJob.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/IJobContext.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IJobContext.cs index 4027081b81..4027081b81 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/IJobContext.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IJobContext.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/JobContext.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobContext.cs index e15c83c88e..e15c83c88e 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/JobContext.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobContext.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/JobSlice.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobSlice.cs index 7802e21ada..7802e21ada 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/JobSlice.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobSlice.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/JobStatus.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobStatus.cs index 02ca3eb1fd..02ca3eb1fd 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/JobStatus.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobStatus.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/ProgressMonitorWrapperJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/ProgressMonitorWrapperJob.cs index b1eea307cf..b1eea307cf 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/ProgressMonitorWrapperJob.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/ProgressMonitorWrapperJob.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/SimpleAnalysisJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/SimpleAnalysisJob.cs index 15878be01b..15878be01b 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Runner/SimpleAnalysisJob.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/SimpleAnalysisJob.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/SeverityGroupingProvider.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/SeverityGroupingProvider.cs index dc129bb35e..dc129bb35e 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/SeverityGroupingProvider.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/SeverityGroupingProvider.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/SolutionAnalysisJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/SolutionAnalysisJob.cs index 785c037dcd..785c037dcd 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/SolutionAnalysisJob.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/SolutionAnalysisJob.cs diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameHandler.cs deleted file mode 100644 index 1b965f684d..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameHandler.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// RenameHandler.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using MonoDevelop.Components.Commands; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Ide.Gui.Content; -using ICSharpCode.NRefactory.CSharp.Refactoring; - -namespace MonoDevelop.Refactoring.Rename -{ - public class RenameHandler : AbstractRefactoringCommandHandler - { - protected override void Update (RefactoringOptions options, CommandInfo info) - { - var renameRefactoring = new RenameRefactoring (); - if (!renameRefactoring.IsValid (options)) - info.Bypass = true; - } - - protected override void Run (RefactoringOptions options) - { - var renameRefactoring = new RenameRefactoring (); - if (renameRefactoring.IsValid (options)) - renameRefactoring.Run (options); - } - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs index cb6bf8acef..b7ebeae5d1 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameItemDialog.cs @@ -32,116 +32,111 @@ using MonoDevelop.Core; using System.Collections.Generic; using MonoDevelop.Ide; using MonoDevelop.Ide.ProgressMonitoring; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.NRefactory.TypeSystem; using System.Linq; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis; namespace MonoDevelop.Refactoring.Rename { public partial class RenameItemDialog : Gtk.Dialog { - RenameRefactoring rename; - RefactoringOptions options; - - public RenameItemDialog (RefactoringOptions options, RenameRefactoring rename) + Func<RenameRefactoring.RenameProperties, IList<Change>> rename; + + public RenameItemDialog (string title, string currentName, Func<RenameRefactoring.RenameProperties, IList<Change>> renameOperation) { - this.options = options; - this.rename = rename; - if (options.SelectedItem is IMethod && ((IMethod)options.SelectedItem).IsConstructor) { - options.SelectedItem = ((IMethod)options.SelectedItem).DeclaringType; - } this.Build (); - includeOverloadsCheckbox.Active = true; - includeOverloadsCheckbox.Visible = false; - if (options.SelectedItem is IType) { + Init (title, currentName, renameOperation); + } - var t = (IType)options.SelectedItem; - if (t.Kind == TypeKind.TypeParameter) { - this.Title = GettextCatalog.GetString ("Rename Type Parameter"); + public RenameItemDialog (ISymbol symbol, RenameRefactoring rename) + { + this.Build (); + + string title; + if (symbol is ITypeSymbol) { + + var t = (ITypeSymbol)symbol; + if (t.TypeKind == TypeKind.TypeParameter) { + title = GettextCatalog.GetString ("Rename Type Parameter"); entry.Text = t.Name; } else { - var typeDefinition = (t).GetDefinition (); - if (typeDefinition.DeclaringType == null) { + var typeDefinition = t; + if (typeDefinition.ContainingType == null) { // not supported for inner types this.renameFileFlag.Visible = true; - this.renameFileFlag.Active = options.Document != null ? options.Document.FileName.FileNameWithoutExtension.Contains (typeDefinition.Name) : false; + this.renameFileFlag.Active = t.Locations.First ().SourceTree.FilePath.Contains (typeDefinition.Name); } else { this.renameFileFlag.Active = false; } - if (typeDefinition.Kind == TypeKind.Interface) - this.Title = GettextCatalog.GetString ("Rename Interface"); + if (typeDefinition.TypeKind == TypeKind.Interface) + title = GettextCatalog.GetString ("Rename Interface"); + else if (typeDefinition.TypeKind == TypeKind.Delegate) + title = GettextCatalog.GetString ("Rename Delegate"); + else if (typeDefinition.TypeKind == TypeKind.Enum) + title = GettextCatalog.GetString ("Rename Enum"); + else if (typeDefinition.TypeKind == TypeKind.Struct) + title = GettextCatalog.GetString ("Rename Struct"); else - this.Title = GettextCatalog.GetString ("Rename Class"); + title = GettextCatalog.GetString ("Rename Class"); } // this.fileName = type.GetDefinition ().Region.FileName; - } else if (options.SelectedItem is IField) { - this.Title = GettextCatalog.GetString ("Rename Field"); - } else if (options.SelectedItem is IProperty) { - if (((IProperty)options.SelectedItem).IsIndexer) { - this.Title = GettextCatalog.GetString ("Rename Indexer"); + } else if (symbol.Kind == SymbolKind.Field) { + title = GettextCatalog.GetString ("Rename Field"); + } else if (symbol.Kind == SymbolKind.Property) { + title = GettextCatalog.GetString ("Rename Property"); + } else if (symbol.Kind == SymbolKind.Event) { + title = GettextCatalog.GetString ("Rename Event"); + } else if (symbol.Kind == SymbolKind.Method) { + var m = (IMethodSymbol)symbol; + if (m.MethodKind == MethodKind.Constructor || + m.MethodKind == MethodKind.StaticConstructor || + m.MethodKind == MethodKind.Destructor) { + title = GettextCatalog.GetString ("Rename Class"); } else { - this.Title = GettextCatalog.GetString ("Rename Property"); + title = GettextCatalog.GetString ("Rename Method"); + includeOverloadsCheckbox.Visible = m.ContainingType.GetMembers (m.Name).Length > 1; } - } else if (options.SelectedItem is IEvent) { - this.Title = GettextCatalog.GetString ("Rename Event"); - } else if (options.SelectedItem is IMethod) { - var m = (IMethod)options.SelectedItem; - if (m.IsConstructor || m.IsDestructor) { - this.Title = GettextCatalog.GetString ("Rename Class"); - } else { - this.Title = GettextCatalog.GetString ("Rename Method"); - includeOverloadsCheckbox.Visible = m.DeclaringType.GetMethods (x => x.Name == m.Name).Count () > 1; - } - } else if (options.SelectedItem is IParameter) { - this.Title = GettextCatalog.GetString ("Rename Parameter"); - } else if (options.SelectedItem is IVariable) { - this.Title = GettextCatalog.GetString ("Rename Variable"); - } else if (options.SelectedItem is ITypeParameter) { - this.Title = GettextCatalog.GetString ("Rename Type Parameter"); - } else if (options.SelectedItem is INamespace) { - this.Title = GettextCatalog.GetString ("Rename namespace"); + } else if (symbol.Kind == SymbolKind.Parameter) { + title = GettextCatalog.GetString ("Rename Parameter"); + } else if (symbol.Kind == SymbolKind.Local) { + title = GettextCatalog.GetString ("Rename Variable"); + } else if (symbol.Kind == SymbolKind.TypeParameter) { + title = GettextCatalog.GetString ("Rename Type Parameter"); + } else if (symbol.Kind == SymbolKind.Namespace) { + title = GettextCatalog.GetString ("Rename Namespace"); + } else if (symbol.Kind == SymbolKind.Label) { + title = GettextCatalog.GetString ("Rename Label"); } else { - this.Title = GettextCatalog.GetString ("Rename Item"); - } - - if (options.SelectedItem is IEntity) { - var member = (IEntity)options.SelectedItem; - if (member.SymbolKind == SymbolKind.Constructor || member.SymbolKind == SymbolKind.Destructor) { - entry.Text = member.DeclaringType.Name; - } else { - entry.Text = member.Name; - } - // fileName = member.Region.FileName; - } else if (options.SelectedItem is IType) { - var lvar = (IType)options.SelectedItem; - entry.Text = lvar.Name; - // this.fileName = lvar.Region.FileName; - } else if (options.SelectedItem is ITypeParameter) { - var lvar = (ITypeParameter)options.SelectedItem; - entry.Text = lvar.Name; - // this.fileName = lvar.Region.FileName; - } else if (options.SelectedItem is IVariable) { - var lvar = (IVariable)options.SelectedItem; - entry.Text = lvar.Name; - // this.fileName = lvar.Region.FileName; - } else if (options.SelectedItem is INamespace) { - var lvar = (INamespace)options.SelectedItem; - entry.Text = lvar.FullName; - // this.fileName = lvar.Region.FileName; + title = GettextCatalog.GetString ("Rename Item"); } + + + Init (title, symbol.Name, prop => rename.PerformChanges (symbol, prop)); + + } + + void Init (string title, string currenName, Func<RenameRefactoring.RenameProperties, IList<Change>> rename) + { + this.Title = title; + this.rename = rename; + + includeOverloadsCheckbox.Active = true; + includeOverloadsCheckbox.Visible = false; + entry.Text = currenName; entry.SelectRegion (0, -1); - + buttonPreview.Sensitive = buttonOk.Sensitive = false; entry.Changed += OnEntryChanged; entry.Activated += OnEntryActivated; - + buttonOk.Clicked += OnOKClicked; buttonPreview.Clicked += OnPreviewClicked; entry.Changed += delegate { buttonPreview.Sensitive = buttonOk.Sensitive = ValidateName (); }; ValidateName (); } + bool ValidateName () { return true; // TODO: Name validation. @@ -186,8 +181,8 @@ namespace MonoDevelop.Refactoring.Rename { var properties = Properties; ((Widget)this).Destroy (); - List<Change> changes = rename.PerformChanges (options, properties); - ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (this.Title, null); + var changes = this.rename (properties); + ProgressMonitor monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (Title, null); RefactoringService.AcceptChanges (monitor, changes); } @@ -195,7 +190,7 @@ namespace MonoDevelop.Refactoring.Rename { var properties = Properties; ((Widget)this).Destroy (); - List<Change> changes = rename.PerformChanges (options, properties); + var changes = this.rename (properties); MessageService.ShowCustomDialog (new RefactoringPreviewDialog (changes)); } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs index 51d2bc74ff..7a490e8f36 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameRefactoring.cs @@ -27,222 +27,133 @@ using System; using System.Collections.Generic; using MonoDevelop.Core; -using Mono.TextEditor; using System.Text; using MonoDevelop.Ide; using System.Linq; -using Mono.TextEditor.PopupWindow; using MonoDevelop.Ide.FindInFiles; using MonoDevelop.Ide.ProgressMonitoring; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; using MonoDevelop.Core.ProgressMonitoring; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.FindSymbols; +using MonoDevelop.Ide.TypeSystem; using MonoDevelop.Ide.Gui; - +using MonoDevelop.Core.Text; +using MonoDevelop.Ide.Editor; +using Microsoft.CodeAnalysis.Rename; namespace MonoDevelop.Refactoring.Rename { - public class RenameRefactoring : RefactoringOperation + public class RenameRefactoring { - public override string AccelKey { - get { - var key = IdeApp.CommandService.GetCommandInfo (MonoDevelop.Ide.Commands.EditCommands.Rename).AccelKey; - return key == null ? null : key.Replace ("dead_circumflex", "^"); - } - } - - public RenameRefactoring () + public static bool Rename (ISymbol symbol, string newName) { - Name = "Rename"; - } - - public override bool IsValid (RefactoringOptions options) - { - if (options.SelectedItem is IVariable || options.SelectedItem is IParameter) - return true; - if (options.SelectedItem is INamespace) { - var ns = (INamespace)options.SelectedItem; - return ns.Types.Any (type => !string.IsNullOrEmpty (type.Region.FileName)); - } - if (options.SelectedItem is ITypeDefinition) - return !string.IsNullOrEmpty (((ITypeDefinition)options.SelectedItem).Region.FileName); - if (options.SelectedItem is IType && ((IType)options.SelectedItem).Kind == TypeKind.TypeParameter) - return !string.IsNullOrEmpty (((ITypeParameter)options.SelectedItem).Region.FileName); - - var member = options.SelectedItem as IMember; - if (member != null) { - if (member.SymbolKind == SymbolKind.Operator) - return false; - var cls = member.DeclaringTypeDefinition; - return cls != null; - } - return false; - } + if (symbol == null) + throw new ArgumentNullException ("symbol"); + if (newName == null) + throw new ArgumentNullException ("newName"); + try { + var result = new RenameRefactoring ().PerformChanges (symbol, new RenameProperties () { NewName = newName }); - public static void Rename (IEntity entity, string newName) - { - if (newName == null) { - var options = new RefactoringOptions () { - SelectedItem = entity - }; - new RenameRefactoring ().Run (options); - return; - } - using (var monitor = new ProgressMonitor ()) { - var col = ReferenceFinder.FindReferences (entity, true, monitor); - - List<Change> result = new List<Change> (); - foreach (var memberRef in col) { - var change = new TextReplaceChange (); - change.FileName = memberRef.FileName; - change.Offset = memberRef.Offset; - change.RemovedChars = memberRef.Length; - change.InsertedText = newName; - change.Description = string.Format (GettextCatalog.GetString ("Replace '{0}' with '{1}'"), memberRef.GetName (), newName); - result.Add (change); - } - if (result.Count > 0) { - RefactoringService.AcceptChanges (monitor, result); + using (var monitor = new ProgressMonitor ()) { + if (result.Count > 0) { + RefactoringService.AcceptChanges (monitor, result); + } } + return true; + } catch (AggregateException ae) { + foreach (var inner in ae.Flatten ().InnerExceptions) + LoggingService.LogError ("Exception while rename.", inner); + return false; + } catch (Exception e) { + LoggingService.LogError ("Exception while rename.", e); + return false; } } - public static void RenameVariable (IVariable variable, string newName) + static void Rollback (TextEditor editor, List<MonoDevelop.Core.Text.TextChangeEventArgs> textChanges) { - using (var monitor = new ProgressMonitor ()) { - var col = ReferenceFinder.FindReferences (variable, true, monitor); - - List<Change> result = new List<Change> (); - foreach (var memberRef in col) { - var change = new TextReplaceChange (); - change.FileName = memberRef.FileName; - change.Offset = memberRef.Offset; - change.RemovedChars = memberRef.Length; - change.InsertedText = newName; - change.Description = string.Format (GettextCatalog.GetString ("Replace '{0}' with '{1}'"), memberRef.GetName (), newName); - result.Add (change); - } - if (result.Count > 0) { - RefactoringService.AcceptChanges (monitor, result); - } + for (int i = textChanges.Count - 1; i >= 0; i--) { + var v = textChanges [i]; + editor.ReplaceText (v.Offset, v.InsertionLength, v.RemovedText); } } - public static void RenameTypeParameter (ITypeParameter typeParameter, string newName) + public void Rename (ISymbol symbol) { - if (newName == null) { - var options = new RefactoringOptions () { - SelectedItem = typeParameter - }; - new RenameRefactoring ().Run (options); + + var solution = IdeApp.ProjectOperations.CurrentSelectedSolution; + var ws = TypeSystemService.GetWorkspace (solution); + + var currentSolution = ws.CurrentSolution; + var newSolution = Renamer.RenameSymbolAsync (currentSolution, symbol, "_" + symbol.Name + "_", ws.Options).Result; + var projectChanges = currentSolution.GetChanges (newSolution).GetProjectChanges ().ToList (); + + if (projectChanges.Count != 1) { + MessageService.ShowCustomDialog (new RenameItemDialog (symbol, this)); return; } - using (var monitor = new ProgressMonitor ()) { - var col = ReferenceFinder.FindReferences (typeParameter, true, monitor); - - List<Change> result = new List<Change> (); - foreach (var memberRef in col) { - var change = new TextReplaceChange (); - change.FileName = memberRef.FileName; - change.Offset = memberRef.Offset; - change.RemovedChars = memberRef.Length; - change.InsertedText = newName; - change.Description = string.Format (GettextCatalog.GetString ("Replace '{0}' with '{1}'"), memberRef.GetName (), newName); - result.Add (change); - } - if (result.Count > 0) { - RefactoringService.AcceptChanges (monitor, result); - } + var projectChange = projectChanges [0]; + var changes = projectChange.GetChangedDocuments ().ToList (); + if (changes.Count != 1) { + MessageService.ShowCustomDialog (new RenameItemDialog (symbol, this)); + return; } - } - - public static void RenameNamespace (INamespace ns, string newName) - { - using (var monitor = new ProgressMonitor ()) { - var col = ReferenceFinder.FindReferences (ns, true, monitor); + var doc = IdeApp.Workbench.ActiveDocument; + var editor = doc.Editor; + + var links = new List<TextLink> (); + var link = new TextLink ("name"); - List<Change> result = new List<Change> (); - foreach (var memberRef in col) { - var change = new TextReplaceChange (); - change.FileName = memberRef.FileName; - change.Offset = memberRef.Offset; - change.RemovedChars = memberRef.Length; - change.InsertedText = newName; - change.Description = string.Format (GettextCatalog.GetString ("Replace '{0}' with '{1}'"), memberRef.GetName (), newName); - result.Add (change); - } - if (result.Count > 0) { - RefactoringService.AcceptChanges (monitor, result); + var cd = changes [0]; + var oldDoc = projectChange.OldProject.GetDocument (cd); + var newDoc = projectChange.NewProject.GetDocument (cd); + var oldVersion = editor.Version; + foreach (var textChange in oldDoc.GetTextChangesAsync (newDoc).Result) { + var segment = new TextSegment (textChange.Span.Start, textChange.Span.Length); + if (segment.Offset <= editor.CaretOffset && editor.CaretOffset <= segment.EndOffset) { + link.Links.Insert (0, segment); + } else { + link.AddLink (segment); } } - } - - - public override string GetMenuDescription (RefactoringOptions options) - { - return IdeApp.CommandService.GetCommandInfo (MonoDevelop.Ide.Commands.EditCommands.Rename).Text; - } - - public override void Run (RefactoringOptions options) - { - if (options.SelectedItem is IVariable) { - var field = options.SelectedItem as IField; - if (field != null && (field.Accessibility != Accessibility.Private || field.DeclaringTypeDefinition != null && field.DeclaringTypeDefinition.Parts.Count > 1)) { - MessageService.ShowCustomDialog (new RenameItemDialog (options, this)); + + links.Add (link); + editor.StartTextLinkMode (new TextLinkModeOptions (links, args => { + if (!args.Success) return; - } - var par = options.SelectedItem as IParameter; - if (par != null && par.Owner != null && (par.Owner.Accessibility != Accessibility.Private || par.Owner.DeclaringTypeDefinition != null && par.Owner.DeclaringTypeDefinition.Parts.Count > 1)) { - MessageService.ShowCustomDialog (new RenameItemDialog (options, this)); + var version = editor.Version; + var span = symbol.Locations.First ().SourceSpan; + var newName = link.CurrentText; + var textChanges = version.GetChangesTo (oldVersion).ToList (); + foreach (var v in textChanges) { + editor.ReplaceText (v.Offset, v.RemovalLength, v.InsertedText); + } + var parsedDocument = doc.UpdateParseDocument (); + if (parsedDocument == null) { + Rollback (editor, textChanges); return; } - - var col = ReferenceFinder.FindReferences (options.SelectedItem, true); - if (col == null) - return; - var data = options.Document != null ? options.GetTextEditorData () : IdeApp.Workbench.ActiveDocument.Editor; - var editor = data.Parent; - if (editor == null) { - MessageService.ShowCustomDialog (new RenameItemDialog (options, this)); + var model = parsedDocument.GetAst<SemanticModel> (); + if (model == null) { + Rollback (editor, textChanges); return; } - - var links = new List<TextLink> (); - var link = new TextLink ("name"); - int baseOffset = Int32.MaxValue; - foreach (var r in col) { - baseOffset = Math.Min (baseOffset, r.Offset); - } - foreach (MemberReference r in col) { - var segment = new TextSegment (r.Offset - baseOffset, r.Length); - if (segment.Offset <= data.Caret.Offset - baseOffset && data.Caret.Offset - baseOffset <= segment.EndOffset) { - link.Links.Insert (0, segment); - } else { - link.AddLink (segment); - } + var node = model.SyntaxTree.GetRoot ().FindNode (span); + if (node == null) { + Rollback (editor, textChanges); + return; } - - links.Add (link); - if (editor.CurrentMode is TextLinkEditMode) - ((TextLinkEditMode)editor.CurrentMode).ExitTextLinkMode (); - TextLinkEditMode tle = new TextLinkEditMode (editor, baseOffset, links); - tle.SetCaretPosition = false; - tle.SelectPrimaryLink = true; - if (tle.ShouldStartTextLinkMode) { - tle.Cancel += delegate { - if (tle.HasChangedText) - editor.Document.Undo (); - }; - tle.OldMode = data.CurrentMode; - tle.StartMode (); - data.CurrentMode = tle; + var sym = model.GetDeclaredSymbol (node); + if (sym == null) { + Rollback (editor, textChanges); + return; } - } else { - MessageService.ShowCustomDialog (new RenameItemDialog (options, this)); - } + if (!Rename (sym, newName)) + Rollback (editor, textChanges); + })); } public class RenameProperties @@ -263,64 +174,66 @@ namespace MonoDevelop.Refactoring.Rename } } - public override List<Change> PerformChanges (RefactoringOptions options, object prop) + public List<Change> PerformChanges (ISymbol symbol, RenameProperties properties) { - RenameProperties properties = (RenameProperties)prop; - List<Change> result = new List<Change> (); - IEnumerable<MemberReference> col = null; - using (var monitor = new MessageDialogProgressMonitor (true, false, false, true)) { - col = ReferenceFinder.FindReferences (options.SelectedItem, properties.IncludeOverloads, monitor); - if (col == null) - return result; - - if (properties.RenameFile && options.SelectedItem is IType) { - var cls = ((IType)options.SelectedItem).GetDefinition (); - int currentPart = 1; - var alreadyRenamed = new HashSet<string> (); - foreach (var part in cls.Parts) { - if (alreadyRenamed.Contains (part.Region.FileName)) - continue; - alreadyRenamed.Add (part.Region.FileName); - - string oldFileName = System.IO.Path.GetFileNameWithoutExtension (part.Region.FileName); - string newFileName; - var newName = properties.NewName; - if (string.IsNullOrEmpty (oldFileName) || string.IsNullOrEmpty (newName)) - continue; - if (oldFileName.ToUpper () == newName.ToUpper () || oldFileName.ToUpper ().EndsWith ("." + newName.ToUpper (), StringComparison.Ordinal)) - continue; - int idx = oldFileName.IndexOf (cls.Name, StringComparison.Ordinal); - if (idx >= 0) { - newFileName = oldFileName.Substring (0, idx) + newName + oldFileName.Substring (idx + cls.Name.Length); - } else { - newFileName = currentPart != 1 ? newName + currentPart : newName; - currentPart++; - } - - int t = 0; - while (System.IO.File.Exists (GetFullFileName (newFileName, part.Region.FileName, t))) { - t++; - } - result.Add (new RenameFileChange (part.Region.FileName, GetFullFileName (newFileName, part.Region.FileName, t))); + var solution = IdeApp.ProjectOperations.CurrentSelectedSolution; + var ws = TypeSystemService.GetWorkspace (solution); + + var newSolution = Renamer.RenameSymbolAsync (ws.CurrentSolution, symbol, properties.NewName, ws.Options).Result; + var result = new List<Change> (); + + foreach (var change in ws.CurrentSolution.GetChanges (newSolution).GetProjectChanges ()) { + foreach (var changedDocument in change.GetChangedDocuments ()) { + var oldDoc = change.OldProject.GetDocument (changedDocument); + var newDoc = change.NewProject.GetDocument (changedDocument); + + foreach (var textChange in oldDoc.GetTextChangesAsync (newDoc).Result.OrderByDescending(ts => ts.Span.Start)) { + var trChange = new TextReplaceChange (); + trChange.FileName = oldDoc.FilePath; + trChange.Offset = textChange.Span.Start; + trChange.RemovedChars = textChange.Span.Length; + trChange.InsertedText = textChange.NewText; + trChange.Description = string.Format (GettextCatalog.GetString ("Replace '{0}' with '{1}'"), symbol.Name, properties.NewName); + result.Add (trChange); } } - - foreach (var memberRef in col) { - TextReplaceChange change = new TextReplaceChange (); - change.FileName = memberRef.FileName; - change.Offset = memberRef.Offset; - change.RemovedChars = memberRef.Length; - change.InsertedText = properties.NewName; - change.Description = string.Format (GettextCatalog.GetString ("Replace '{0}' with '{1}'"), memberRef.GetName (), properties.NewName); - result.Add (change); + } + + if (properties.RenameFile && symbol.Kind == SymbolKind.NamedType) { + int currentPart = 1; + var alreadyRenamed = new HashSet<string> (); + foreach (var part in symbol.Locations) { + var filePath = part.SourceTree.FilePath; + if (alreadyRenamed.Contains (filePath)) + continue; + alreadyRenamed.Add (filePath); + + string oldFileName = System.IO.Path.GetFileNameWithoutExtension (filePath); + string newFileName; + if (oldFileName.ToUpper () == properties.NewName.ToUpper () || oldFileName.ToUpper ().EndsWith ("." + properties.NewName.ToUpper (), StringComparison.Ordinal)) + continue; + int idx = oldFileName.IndexOf (symbol.Name, StringComparison.Ordinal); + if (idx >= 0) { + newFileName = oldFileName.Substring (0, idx) + properties.NewName + oldFileName.Substring (idx + symbol.Name.Length); + } else { + newFileName = currentPart != 1 ? properties.NewName + currentPart : properties.NewName; + currentPart++; + } + + int t = 0; + while (System.IO.File.Exists (GetFullFileName (newFileName, filePath, t))) { + t++; + } + result.Add (new RenameFileChange (filePath, GetFullFileName (newFileName, filePath, t))); } } + return result; } static string GetFullFileName (string fileName, string oldFullFileName, int tryCount) { - StringBuilder name = new StringBuilder (fileName); + var name = new StringBuilder (fileName); if (tryCount > 0) { name.Append ("_"); name.Append (tryCount.ToString ()); diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameTextEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameTextEditorExtension.cs deleted file mode 100644 index c2e6e44360..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.Rename/RenameTextEditorExtension.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// RenameTextEditorExtension.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using MonoDevelop.Ide.Commands; -using MonoDevelop.Components.Commands; -using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Ide; - -namespace MonoDevelop.Refactoring.Rename -{ - public class RenameTextEditorExtension : TextEditorExtension - { - [CommandUpdateHandler(EditCommands.Rename)] - public void RenameCommand_Update(CommandInfo ci) - { - new RenameHandler ().UpdateCommandInfo (ci); - } - - [CommandHandler (EditCommands.Rename)] - public void RenameCommand () - { - new RenameHandler ().Start (base.Editor); - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml index 8151d80966..92ded99638 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.addin.xml @@ -12,21 +12,9 @@ <ExtensionPoint path = "/MonoDevelop/Refactoring/ASTProvider" name = "ASTProviders"> <ExtensionNode name="Class"/> </ExtensionPoint> - - <ExtensionPoint path = "/MonoDevelop/Refactoring/CodeActions" name = "CodeAction"> - <ExtensionNode name="Action" type ="MonoDevelop.CodeActions.CodeActionAddinNode"/> - </ExtensionPoint> - - <ExtensionPoint path = "/MonoDevelop/Refactoring/CodeActionSource" name = "CodeActionSource"> - <ExtensionNode name="Source"/> - </ExtensionPoint> - - <ExtensionPoint path = "/MonoDevelop/Refactoring/CodeIssues" name = "CodeIssue"> - <ExtensionNode name="CodeIssue" type ="MonoDevelop.CodeIssues.CodeIssueAddinNode"/> - </ExtensionPoint> - - <ExtensionPoint path = "/MonoDevelop/Refactoring/CodeIssueSource" name = "CodeIssueSource"> - <ExtensionNode name="Source"/> + + <ExtensionPoint path = "/MonoDevelop/Refactoring/CodeDiagnosticProvider" name = "Code Diagnostic Provider"> + <ExtensionNode name="Class"/> </ExtensionPoint> <ExtensionNodeSet id="MonoDevelop.AnalysisCore.Rules"> @@ -70,44 +58,26 @@ <!-- RefactoryCommands --> <Extension path = "/MonoDevelop/Ide/Commands"> - + <Category _name = "Code Navigation" id = "CodeNavigation"> - <Command id = "MonoDevelop.Refactoring.RefactoryCommands.GotoDeclaration" - defaultHandler = "MonoDevelop.Refactoring.GotoDeclarationHandler" - _label = "_Go to Declaration" - shortcut = "F12" - macShortcut = "Meta|D"/> <Command id = "MonoDevelop.Refactoring.RefactoryCommands.FindReferences" - defaultHandler = "MonoDevelop.Refactoring.FindReferencesHandler" _label = "_Find References" shortcut = "Shift|F12" macShortcut = "Shift|Meta|R"/> <Command id = "MonoDevelop.Refactoring.RefactoryCommands.FindAllReferences" - defaultHandler = "MonoDevelop.Refactoring.FindAllReferencesHandler" _label = "_Find References of All Overloads" /> <Command id = "MonoDevelop.Refactoring.RefactoryCommands.FindDerivedClasses" - defaultHandler = "MonoDevelop.Refactoring.FindDerivedClassesHandler" _label = "Find _Derived Symbols" /> </Category> <Category _name = "Refactoring" id = "Refactoring"> - <Command id = "MonoDevelop.Refactoring.RefactoryCommands.Resolve" - defaultHandler = "MonoDevelop.Refactoring.ResolveCommandHandler" - type="array" - _label = "Resolve"/> - - <Command id = "MonoDevelop.Refactoring.RefactoryCommands.CurrentRefactoryOperations" - defaultHandler = "MonoDevelop.Refactoring.CurrentRefactoryOperationsHandler" - type="array" - _label = "Refactory Operations" /> - + <Command id = "MonoDevelop.Refactoring.RefactoryCommands.QuickFix" _label = "Quick Fix..." shortcut = "Alt|Return" macShortcut = "Alt|Return" /> <Command id = "MonoDevelop.Refactoring.RefactoryCommands.ImportSymbol" - defaultHandler = "MonoDevelop.Refactoring.ImportSymbolHandler" _label = "Import Symbol..." shortcut = "Control|Alt|space" macShortcut = "Control|Alt|space" /> @@ -120,20 +90,7 @@ </Category> </Extension> - <Extension path = "/MonoDevelop/SourceEditor2/ContextMenu/Editor"> - <CommandItem id = "MonoDevelop.Refactoring.RefactoryCommands.Resolve" insertbefore="MonoDevelop.SourceEditor.SourceEditorCommands.MarkerOperations"/> - - <ItemSet id = "Fix" _label = "Fix" autohide="true" - insertafter="MonoDevelop.SourceEditor.SourceEditorCommands.MarkerOperations" insertbefore="MonoDevelop.Debugger.DebugCommands.ExpressionEvaluator"> - <CommandItem id = "MonoDevelop.AnalysisCore.AnalysisCommands.FixOperations" /> - </ItemSet> - - - <CommandItem id = "MonoDevelop.Refactoring.RefactoryCommands.CurrentRefactoryOperations" insertafter="MonoDevelop.SourceEditor.SourceEditorCommands.MarkerOperations" insertbefore="MonoDevelop.Debugger.DebugCommands.ExpressionEvaluator"/> - </Extension> - <Extension path = "/MonoDevelop/Ide/TextEditorExtensions"> - <Class class = "MonoDevelop.Refactoring.Rename.RenameTextEditorExtension" /> <Class class = "MonoDevelop.CodeActions.CodeActionEditorExtension" /> </Extension> @@ -145,9 +102,6 @@ <!-- Quick fix commands --> <Extension path = "/MonoDevelop/Ide/Commands/Refactoring"> - <Command id = "MonoDevelop.AnalysisCore.AnalysisCommands.FixOperations" type="array" - defaultHandler="MonoDevelop.AnalysisCore.FixOperationsHandler" - _label = "Fixes" /> <Command id = "MonoDevelop.AnalysisCore.AnalysisCommands.ShowFixes" defaultHandler="MonoDevelop.AnalysisCore.ShowFixesHandler" _label = "Show Fixes" @@ -170,13 +124,13 @@ <!-- Extensions to the addin points defined by this addin --> <Extension path = "/MonoDevelop/AnalysisCore/Types"> - <Type name="Document" class="MonoDevelop.Ide.Gui.Document" /> + <Type name="AnalysisDocument" class="MonoDevelop.AnalysisCore.Gui.AnalysisDocument" /> <Type name="CompilationUnit" class="MonoDevelop.Projects.Dom.ICompilationUnit" /> </Extension> <Extension path = "/MonoDevelop/AnalysisCore/Rules"> <Adaptor func="MonoDevelop.AnalysisCore.Rules.Adapters.GetCompilationUnit" - input="Document" output="CompilationUnit" /> + input="AnalysisDocument" output="CompilationUnit" /> <Category _name="Design Guidelines" id="Design"> <!-- <Rule _name="Naming Conventions" input="CompilationUnit" func="MonoDevelop.AnalysisCore.Rules.NamingConventions.ClassNaming" />--> diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj index d47fae2ad7..291163ce86 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.csproj @@ -74,6 +74,67 @@ <Reference Include="System.Core" /> <Reference Include="System.Xml" /> <Reference Include="Mono.Cairo" /> + <Reference Include="System.ComponentModel.Composition" /> + <Reference Include="System.Collections.Immutable"> + <HintPath>..\..\..\packages\System.Collections.Immutable.1.1.33-beta\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System.Reflection.Metadata"> + <HintPath>..\..\..\packages\System.Reflection.Metadata.1.0.18-beta\lib\portable-net45+win8\System.Reflection.Metadata.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Desktop"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.Desktop.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp.Desktop"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.CSharp.Desktop.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.CSharp.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Workspaces.Desktop"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.Workspaces.Desktop.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.Workspaces"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.Workspaces.Common.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.Workspaces.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces.Desktop"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.Desktop.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="Microsoft.CodeAnalysis.CSharp.Workspaces"> + <HintPath>..\..\..\packages\Microsoft.CodeAnalysis.CSharp.Workspaces.1.0.0-rc1\lib\net45\Microsoft.CodeAnalysis.CSharp.Workspaces.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System.Composition.AttributedModel"> + <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.AttributedModel.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System.Composition.Convention"> + <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Convention.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System.Composition.Hosting"> + <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Hosting.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System.Composition.Runtime"> + <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.Runtime.dll</HintPath> + <Private>False</Private> + </Reference> + <Reference Include="System.Composition.TypedParts"> + <HintPath>..\..\..\packages\Microsoft.Composition.1.0.27\lib\portable-net45+win8+wp8+wpa81\System.Composition.TypedParts.dll</HintPath> + <Private>False</Private> + </Reference> <Reference Include="Xamarin.Mac" Condition=" '$(Configuration)' == 'DebugMac' Or '$(Configuration)' == 'ReleaseMac' "> <HintPath>..\..\..\external\Xamarin.Mac.dll</HintPath> <Private>False</Private> @@ -95,86 +156,40 @@ <Compile Include="MonoDevelop.AnalysisCore\AnalysisOptions.cs" /> <Compile Include="MonoDevelop.AnalysisCore\AnalysisService.cs" /> <Compile Include="MonoDevelop.AnalysisCore\FixableResult.cs" /> - <Compile Include="MonoDevelop.AnalysisCore\Rules\Adaptors.cs" /> <Compile Include="MonoDevelop.AnalysisCore\Result.cs" /> <Compile Include="MonoDevelop.AnalysisCore\RuleTree.cs" /> <Compile Include="MonoDevelop.AnalysisCore\RuleTreeType.cs" /> <Compile Include="MonoDevelop.AnalysisCore\Fixes\GenericFix.cs" /> <Compile Include="MonoDevelop.Refactoring\RefactoringService.cs" /> - <Compile Include="MonoDevelop.Refactoring\RefactoryCommands.cs" /> - <Compile Include="MonoDevelop.Refactoring\RefactoringOperation.cs" /> <Compile Include="MonoDevelop.Refactoring\Change.cs" /> - <Compile Include="MonoDevelop.Refactoring\GotoDeclarationHandler.cs" /> - <Compile Include="MonoDevelop.Refactoring\FindReferencesHandler.cs" /> - <Compile Include="MonoDevelop.Refactoring.Rename\RenameTextEditorExtension.cs" /> <Compile Include="MonoDevelop.Refactoring.Rename\RenameRefactoring.cs" /> <Compile Include="MonoDevelop.Refactoring.Rename\RenameItemDialog.cs" /> - <Compile Include="MonoDevelop.Refactoring.Rename\RenameHandler.cs" /> <Compile Include="gtk-gui\MonoDevelop.Refactoring.Rename.RenameItemDialog.cs" /> - <Compile Include="MonoDevelop.Refactoring\AbstractRefactoringCommandHandler.cs" /> <Compile Include="MonoDevelop.Refactoring\RefactoringOptions.cs" /> <Compile Include="MonoDevelop.Refactoring\RefactoringPreviewDialog.cs" /> <Compile Include="gtk-gui\MonoDevelop.Refactoring.RefactoringPreviewDialog.cs" /> - <Compile Include="MonoDevelop.Refactoring\FindDerivedClassesHandler.cs" /> - <Compile Include="MonoDevelop.Refactoring\ImportSymbolHandler.cs" /> - <Compile Include="MonoDevelop.CodeIssues\CodeIssueProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\CodeIssue.cs" /> <Compile Include="MonoDevelop.CodeActions\CodeActionEditorExtension.cs" /> - <Compile Include="MonoDevelop.CodeActions\CodeAction.cs" /> - <Compile Include="MonoDevelop.CodeActions\CodeActionProvider.cs" /> - <Compile Include="MonoDevelop.CodeActions\CodeActionAddinNode.cs" /> <Compile Include="MonoDevelop.CodeActions\CodeActionPanelWidget.cs" /> - <Compile Include="MonoDevelop.CodeActions\AnalysisCodeAction.cs" /> <Compile Include="gtk-gui\MonoDevelop.CodeActions.ContextActionPanelWidget.cs" /> <Compile Include="MonoDevelop.CodeIssues\CodeIssuePanelWidget.cs" /> <Compile Include="gtk-gui\MonoDevelop.CodeIssues.CodeIssuePanelWidget.cs" /> - <Compile Include="MonoDevelop.CodeActions\ICodeActionProviderSource.cs" /> - <Compile Include="MonoDevelop.CodeIssues\ICodeIssueProviderSource.cs" /> - <Compile Include="MonoDevelop.CodeIssues\CodeAnalysisRunner.cs" /> - <Compile Include="MonoDevelop.CodeIssues\DefaultCodeIssueCategories.cs" /> - <Compile Include="MonoDevelop.CodeIssues\CodeIssueAddinNode.cs" /> - <Compile Include="MonoDevelop.Refactoring\ResolveCommandHandler.cs" /> - <Compile Include="MonoDevelop.Refactoring\ExtensionMethods.cs" /> - <Compile Include="MonoDevelop.CodeIssues\CodeIssuePad.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IGroupingProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IssueSummary.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IssueGroup.cs" /> - <Compile Include="MonoDevelop.CodeIssues\CategoryGroupingProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\GroupingProviderChainControl.cs" /> - <Compile Include="MonoDevelop.CodeIssues\GroupingDescriptionAttribute.cs" /> - <Compile Include="MonoDevelop.CodeIssues\NullGroupingProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IssueGroupEventArgs.cs" /> - <Compile Include="MonoDevelop.CodeIssues\GroupingProviderEventArgs.cs" /> - <Compile Include="MonoDevelop.CodeIssues\AbstractGroupingProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\ProviderGroupingProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\SeverityGroupingProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\AnalysisState.cs" /> - <Compile Include="MonoDevelop.CodeIssues\AnalysisStateChangeEventArgs.cs" /> - <Compile Include="MonoDevelop.CodeIssues\CodeAnalysisBatchRunner.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IIssueTreeNode.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IIssueSummarySink.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IssueTreeNodeEventArgs.cs" /> - <Compile Include="MonoDevelop.CodeIssues\ActionSummary.cs" /> - <Compile Include="MonoDevelop.CodeIssues\BatchFixer.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IssueMatch.cs" /> - <Compile Include="MonoDevelop.CodeIssues\ExactIssueMatcher.cs" /> - <Compile Include="MonoDevelop.CodeIssues\IActionMatcher.cs" /> <Compile Include="AddinInfo.cs" /> - <Compile Include="MonoDevelop.Refactoring\FindDerivedSymbolsHandler.cs" /> - <Compile Include="MonoDevelop.Refactoring\FindMemberOverloadsHandler.cs" /> - <Compile Include="MonoDevelop.Refactoring\FindExtensionMethodHandler.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\IAnalysisJob.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\AnalysisJobQueue.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\CodeIssueEventArgs.cs" /> - <Compile Include="MonoDevelop.CodeIssues\SolutionAnalysisJob.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\SimpleAnalysisJob.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\ProgressMonitorWrapperJob.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\JobContext.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\IJobContext.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\JobSlice.cs" /> - <Compile Include="MonoDevelop.CodeIssues\Runner\JobStatus.cs" /> - <Compile Include="MonoDevelop.CodeIssues\ProjectGroupingProvider.cs" /> - <Compile Include="MonoDevelop.CodeIssues\FileGroupingProvider.cs" /> + <Compile Include="MonoDevelop.CodeIssues\DiagnosticResult.cs" /> + <Compile Include="MonoDevelop.CodeActions\CodeRefactoringDescriptor.cs" /> + <Compile Include="MonoDevelop.CodeActions\CodeRefactoringService.cs" /> + <Compile Include="MonoDevelop.CodeIssues\CodeDiagnosticDescriptor.cs" /> + <Compile Include="MonoDevelop.CodeIssues\CodeDiagnosticRunner.cs" /> + <Compile Include="MonoDevelop.CodeActions\CodeActionContainer.cs" /> + <Compile Include="MonoDevelop.AnalysisCore\IssueMarker.cs" /> + <Compile Include="MonoDevelop.Refactoring\InsertionPointService.cs" /> + <Compile Include="MonoDevelop.CodeIssues\CodeDiagnosticProvider.cs" /> + <Compile Include="MonoDevelop.CodeIssues\BuiltInCodeDiagnosticProvider.cs" /> + <Compile Include="MonoDevelop.CodeIssues\AnalyzersFromAssembly.cs" /> + <Compile Include="MonoDevelop.CodeActions\ValidCodeAction.cs" /> + <Compile Include="MonoDevelop.CodeActions\ValidCodeDiagnosticAction.cs" /> + <Compile Include="MonoDevelop.CodeIssues\CodeDiagnosticFixDescriptor.cs" /> + <Compile Include="MonoDevelop.Refactoring\Commands.cs" /> + <Compile Include="MonoDevelop.Refactoring\RefactoringSymbolInfo.cs" /> </ItemGroup> <ItemGroup> <Folder Include="MonoDevelop.Refactoring\" /> @@ -182,7 +197,8 @@ <Folder Include="MonoDevelop.AnalysisCore\" /> <Folder Include="MonoDevelop.CodeIssues\" /> <Folder Include="MonoDevelop.CodeActions\" /> - <Folder Include="MonoDevelop.CodeIssues\Runner\" /> + <Folder Include="MonoDevelop.AnalysisCore\Rules\" /> + <Folder Include="MonoDevelop.CodeIssues\Pad\" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDevelop.Refactoring.addin.xml"> @@ -223,31 +239,11 @@ <Name>MonoDevelop.Core</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\..\core\Mono.Texteditor\Mono.TextEditor.csproj"> - <Project>{A2329308-3751-4DBD-9A75-5F7B8B024625}</Project> - <Name>Mono.TextEditor</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\MonoDevelop.DesignerSupport\MonoDevelop.DesignerSupport.csproj"> <Project>{2C24D515-4A2C-445C-8419-C09231913CFA}</Project> <Name>MonoDevelop.DesignerSupport</Name> <Private>False</Private> </ProjectReference> - <ProjectReference Include="..\MonoDevelop.SourceEditor2\MonoDevelop.SourceEditor.csproj"> - <Project>{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}</Project> - <Name>MonoDevelop.SourceEditor</Name> - <Private>False</Private> - </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj"> - <Project>{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}</Project> - <Name>ICSharpCode.NRefactory</Name> - <Private>False</Private> - </ProjectReference> - <ProjectReference Include="..\..\..\external\nrefactory\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj"> - <Project>{53DCA265-3C3C-42F9-B647-F72BA678122B}</Project> - <Name>ICSharpCode.NRefactory.CSharp</Name> - <Private>False</Private> - </ProjectReference> <ProjectReference Include="..\MonoDevelop.Debugger\MonoDevelop.Debugger.csproj"> <Project>{2357AABD-08C7-4808-A495-8FF2D3CDFDB0}</Project> <Name>MonoDevelop.Debugger</Name> @@ -268,15 +264,65 @@ <Name>Mono.Debugging</Name> <Private>False</Private> </ProjectReference> + <ProjectReference Include="..\..\..\external\NRefactory6\ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory6.CSharp.csproj"> + <Project>{7E891659-45F3-42B5-B940-A728780CCAE9}</Project> + <Name>ICSharpCode.NRefactory6.CSharp</Name> + <Private>False</Private> + </ProjectReference> + <ProjectReference Include="..\..\..\external\NRefactory6\ICSharpCode.NRefactory.CSharp.Refactoring\ICSharpCode.NRefactory6.CSharp.Refactoring.csproj"> + <Project>{C465A5DC-AD28-49A2-89C0-F81838814A7E}</Project> + <Name>ICSharpCode.NRefactory6.CSharp.Refactoring</Name> + <Private>False</Private> + </ProjectReference> + <ProjectReference Include="..\MonoDevelop.SourceEditor2\MonoDevelop.SourceEditor.csproj"> + <Project>{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}</Project> + <Name>MonoDevelop.SourceEditor</Name> + <Private>False</Private> + </ProjectReference> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup> <None Include="MonoDevelop.AnalysisCore\README.txt" /> <None Include="MonoDevelop.AnalysisCore\TODO.txt" /> <None Include="MonoDevelop.Refactoring\QuickFixHandler.cs" /> - <None Include="MonoDevelop.Refactoring\EncapsulateFieldDialog.cs" /> - <None Include="MonoDevelop.Refactoring\OverridesImplementsDialog.cs" /> <None Include="gtk-gui\MonoDevelop.Refactoring.OverridesImplementsDialog.cs" /> <None Include="gtk-gui\MonoDevelop.Refactoring.EncapsulateFieldDialog.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\AnalysisJobQueue.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\CodeIssueEventArgs.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\IAnalysisJob.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\IJobContext.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\JobContext.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\JobSlice.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\JobStatus.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\ProgressMonitorWrapperJob.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\Runner\SimpleAnalysisJob.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\CodeIssuePad.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\ExactIssueMatcher.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IActionMatcher.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IssueMatch.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\SolutionAnalysisJob.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\CodeAnalysisBatchRunner.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\BatchFixer.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\AbstractGroupingProvider.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\FileGroupingProvider.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\GroupingDescriptionAttribute.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\GroupingProviderChainControl.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\GroupingProviderEventArgs.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IGroupingProvider.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IIssueSummarySink.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IIssueTreeNode.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IssueGroup.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IssueGroupEventArgs.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IssueSummary.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\IssueTreeNodeEventArgs.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\NullGroupingProvider.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\ProjectGroupingProvider.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\ProviderGroupingProvider.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\SeverityGroupingProvider.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\ActionSummary.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\AnalysisState.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\AnalysisStateChangeEventArgs.cs" /> + <None Include="MonoDevelop.CodeIssues\Pad\CategoryGroupingProvider.cs" /> + <None Include="packages.config" /> </ItemGroup> </Project> diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/AbstractRefactoringCommandHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/AbstractRefactoringCommandHandler.cs deleted file mode 100644 index cf29ac7626..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/AbstractRefactoringCommandHandler.cs +++ /dev/null @@ -1,90 +0,0 @@ -// -// AbstractRefactoringCommandHandler.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using MonoDevelop.Components.Commands; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.Semantics; - -namespace MonoDevelop.Refactoring -{ - public abstract class AbstractRefactoringCommandHandler : CommandHandler - { - protected abstract void Run (RefactoringOptions options); - - protected virtual void Update (RefactoringOptions options, CommandInfo info) - { - } - - public void UpdateCommandInfo (CommandInfo info) - { - Update (info); - } - - public void Start (object data) - { - Run (data); - } - - RefactoringOptions CreateOptions () - { - Document doc = IdeApp.Workbench.ActiveDocument; - if (doc == null) - return null; - - ResolveResult result; - var item = CurrentRefactoryOperationsHandler.GetItem (doc, out result); - - return new RefactoringOptions (doc) { - ResolveResult = result, - SelectedItem = item - }; - } - - protected override void Update (CommandInfo info) - { - base.Update (info); - - var options = CreateOptions (); - if (options != null) { - Update (options, info); - } else { - info.Bypass = true; - } - } - - protected override void Run (object data) - { - var options = CreateOptions (); - if (options != null) - Run (options); - } - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs index 3b09f630f7..ca05849af7 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Change.cs @@ -28,11 +28,10 @@ using System; using System.IO; using System.Collections.Generic; using MonoDevelop.Core; -using MonoDevelop.Projects.Text; -using Mono.TextEditor; using MonoDevelop.Projects; using MonoDevelop.Ide; -using ICSharpCode.NRefactory.CSharp.Refactoring; +using MonoDevelop.Ide.Editor; +using MonoDevelop.Core.Text; namespace MonoDevelop.Refactoring { @@ -84,26 +83,23 @@ namespace MonoDevelop.Refactoring set; } - static List<TextEditorData> textEditorDatas = new List<TextEditorData> (); + static List<TextEditor> textEditorDatas = new List<TextEditor> (); static List<IDisposable> undoGroups = new List<IDisposable> (); public static void FinishRefactoringOperation () { - foreach (TextEditorData data in textEditorDatas) { - data.Document.CommitUpdateAll (); - } textEditorDatas.Clear (); undoGroups.ForEach (grp => grp.Dispose ()); undoGroups.Clear (); } - internal static TextEditorData GetTextEditorData (string fileName) + internal static TextEditor GetTextEditorData (string fileName) { if (IdeApp.Workbench == null) return null; foreach (var doc in IdeApp.Workbench.Documents) { if (doc.FileName == fileName) { - TextEditorData result = doc.Editor; + var result = doc.Editor; if (result != null) { textEditorDatas.Add (result); undoGroups.Add (result.OpenUndoGroup ()); @@ -113,7 +109,7 @@ namespace MonoDevelop.Refactoring } return null; } - protected virtual TextEditorData TextEditorData { + protected virtual TextEditor TextEditorData { get { return GetTextEditorData (FileName); } @@ -123,33 +119,16 @@ namespace MonoDevelop.Refactoring if (rctx == null) throw new InvalidOperationException ("Refactory context not available."); - TextEditorData textEditorData = this.TextEditorData; - bool saveEditor = false; - bool hadBom = true; - System.Text.Encoding encoding = System.Text.Encoding.UTF8; + var textEditorData = this.TextEditorData; if (textEditorData == null) { bool open; - textEditorData = TextFileProvider.Instance.GetTextEditorData (FileName, out hadBom, out encoding, out open); - saveEditor = true; - } - - - int offset = textEditorData.Caret.Offset; - int charsInserted = textEditorData.Replace (Offset, RemovedChars, InsertedText); - if (MoveCaretToReplace) { - textEditorData.Caret.Offset = Offset + charsInserted; + var data = TextFileProvider.Instance.GetTextEditorData (FileName, out open); + data.ReplaceText (Offset, RemovedChars, InsertedText); + data.Save (); } else { - if (Offset < offset) { - int rem = RemovedChars; - if (Offset + rem > offset) - rem = offset - Offset; - textEditorData.Caret.Offset = offset - rem + charsInserted; - } + textEditorData.ReplaceText (Offset, RemovedChars, InsertedText); } - - if (saveEditor) - Mono.TextEditor.Utils.TextFileUtility.WriteText (FileName, textEditorData.Text, encoding, hadBom); } public override string ToString () @@ -180,8 +159,8 @@ namespace MonoDevelop.Refactoring public override void PerformChange (ProgressMonitor monitor, RefactoringOptions rctx) { File.WriteAllText (FileName, Content); - rctx.Document.Project.AddFile (FileName); - IdeApp.ProjectOperations.SaveAsync (rctx.Document.Project); + rctx.DocumentContext.Project.AddFile (FileName); + IdeApp.ProjectOperations.SaveAsync (rctx.DocumentContext.Project); } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Commands.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Commands.cs new file mode 100644 index 0000000000..856fcc63cd --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/Commands.cs @@ -0,0 +1,44 @@ +// +// Commands.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace MonoDevelop.Refactoring +{ + + public enum RefactoryCommands + { + CurrentRefactoryOperations, + GotoDeclaration, // in 'referenced' in IdeViMode.cs as string + FindReferences, + FindAllReferences, + FindDerivedClasses, + DeclareLocal, + ImportSymbol, + QuickFix + } + +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/EncapsulateFieldDialog.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/EncapsulateFieldDialog.cs deleted file mode 100644 index 7c806bbfcc..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/EncapsulateFieldDialog.cs +++ /dev/null @@ -1,469 +0,0 @@ -// EncapsulateFieldDialog.cs -// -// Author: -// Jeffrey Stedfast <fejj@novell.com> -// Ankit Jain <jankit@novell.com> -// -// Copyright (c) 2007 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - - -using System; -using System.Text; -using System.CodeDom; - -using Gtk; - -using MonoDevelop.Core; -using MonoDevelop.Projects.Dom; -using MonoDevelop.Projects.Dom.Parser; -using MonoDevelop.Projects.CodeGeneration; -using MonoDevelop.Ide; -using Mono.TextEditor; -using System.Linq; -using System.Collections.Generic; -using Mono.TextEditor.PopupWindow; - -namespace MonoDevelop.Refactoring { - - public partial class EncapsulateFieldDialog : Gtk.Dialog - { - IType declaringType; - ListStore store; - ListStore visibilityStore; - MonoDevelop.Ide.Gui.Document editor; - - private const int colCheckedIndex = 0; - private const int colFieldNameIndex = 1; - private const int colPropertyNameIndex = 2; - private const int colVisibilityIndex = 3; - private const int colReadOnlyIndex = 4; - private const int colFieldIndex = 5; - - public EncapsulateFieldDialog (MonoDevelop.Ide.Gui.Document editor, ITypeResolveContext ctx, IType declaringType) - : this (editor, declaringType, null) - {} - - public EncapsulateFieldDialog (MonoDevelop.Ide.Gui.Document editor, ITypeResolveContext ctx, IField field) - : this (editor, field.DeclaringType, field) - {} - - private EncapsulateFieldDialog (MonoDevelop.Ide.Gui.Document editor, IType declaringType, IField field) - { - this.editor = editor; - this.declaringType = declaringType; - this.Build (); - - Title = GettextCatalog.GetString ("Encapsulate Fields"); - buttonOk.Sensitive = true; - store = new ListStore (typeof (bool), typeof(string), typeof (string), typeof (string), typeof (bool), typeof (IField)); - visibilityStore = new ListStore (typeof (string)); - - // Column #1 - CellRendererToggle cbRenderer = new CellRendererToggle (); - cbRenderer.Activatable = true; - cbRenderer.Toggled += OnSelectedToggled; - TreeViewColumn cbCol = new TreeViewColumn (); - cbCol.Title = ""; - cbCol.PackStart (cbRenderer, false); - cbCol.AddAttribute (cbRenderer, "active", colCheckedIndex); - treeview.AppendColumn (cbCol); - - // Column #2 - CellRendererText fieldRenderer = new CellRendererText (); - fieldRenderer.Weight = (int) Pango.Weight.Bold; - TreeViewColumn fieldCol = new TreeViewColumn (); - fieldCol.Title = GettextCatalog.GetString ("Field"); - fieldCol.Expand = true; - fieldCol.PackStart (fieldRenderer, true); - fieldCol.AddAttribute (fieldRenderer, "text", colFieldNameIndex); - treeview.AppendColumn (fieldCol); - - // Column #3 - CellRendererText propertyRenderer = new CellRendererText (); - propertyRenderer.Editable = true; - propertyRenderer.Edited += new EditedHandler (OnPropertyEdited); - TreeViewColumn propertyCol = new TreeViewColumn (); - propertyCol.Title = GettextCatalog.GetString ("Property"); - propertyCol.Expand = true; - propertyCol.PackStart (propertyRenderer, true); - propertyCol.AddAttribute (propertyRenderer, "text", colPropertyNameIndex); - propertyCol.SetCellDataFunc (propertyRenderer, new TreeCellDataFunc (RenderPropertyName)); - treeview.AppendColumn (propertyCol); - - // Column #4 - CellRendererCombo visiComboRenderer = new CellRendererCombo (); - visiComboRenderer.Model = visibilityStore; - visiComboRenderer.Editable = true; - visiComboRenderer.Edited += new EditedHandler (OnVisibilityEdited); - visiComboRenderer.HasEntry = false; - visiComboRenderer.TextColumn = 0; - - TreeViewColumn visiCol = new TreeViewColumn (); - visiCol.Title = GettextCatalog.GetString ("Visibility"); - visiCol.PackStart (visiComboRenderer, false); - visiCol.AddAttribute (visiComboRenderer, "text", colVisibilityIndex); - treeview.AppendColumn (visiCol); - - // Column #5 - CellRendererToggle roRenderer = new CellRendererToggle (); - roRenderer.Activatable = true; - roRenderer.Xalign = 0.0f; - roRenderer.Toggled += new ToggledHandler (OnReadOnlyToggled); - TreeViewColumn roCol = new TreeViewColumn (); - roCol.Title = GettextCatalog.GetString ("Read only"); - roCol.PackStart (roRenderer, false); - roCol.AddAttribute (roRenderer, "active", colReadOnlyIndex); - treeview.AppendColumn (roCol); - - visibilityStore.AppendValues ("Public"); - visibilityStore.AppendValues ("Private"); - visibilityStore.AppendValues ("Protected"); - visibilityStore.AppendValues ("Internal"); - - treeview.Model = store; - - foreach (IField ifield in declaringType.Fields) { - bool enabled = field != null && (field.Name == ifield.Name); - string propertyName = GeneratePropertyName (ifield.Name); - store.AppendValues (enabled, ifield.Name, propertyName, - "Public", ifield.IsReadonly || ifield.IsLiteral, ifield); - - if (enabled) - CheckAndUpdateConflictMessage (propertyName, false); - } - - store.SetSortColumnId (colFieldNameIndex, SortType.Ascending); - buttonSelectAll.Clicked += OnSelectAllClicked; - buttonUnselectAll.Clicked += OnUnselectAllClicked; - buttonOk.Clicked += OnOKClicked; - buttonCancel.Clicked += OnCancelClicked; - - UpdateOKButton (); - } - - string GeneratePropertyName (string fieldName) - { - StringBuilder builder = new StringBuilder (fieldName.Length); - bool upper = true; - int i = 0; - - // Field names are commonly prefixed with "m" or "m_" by devs from c++ land. - if (fieldName[0] == 'm' && fieldName.Length > 1 && - (fieldName[1] == '_' || Char.IsUpper (fieldName[1]))) - i++; - - while (i < fieldName.Length) { - if (fieldName[i] == '_') { - // strip _'s and uppercase the next letter - upper = true; - } else if (Char.IsLetter (fieldName[i])) { - builder.Append (upper ? Char.ToUpper (fieldName[i]) : fieldName[i]); - upper = false; - } else { - builder.Append (fieldName[i]); - } - - i++; - } - - return builder.ToString (); - } - - void OnPropertyEdited (object sender, EditedArgs args) - { - TreeIter iter; - if (!store.GetIterFromString (out iter, args.Path)) - return; - - store.SetValue (iter, colPropertyNameIndex, args.NewText); - if (!CheckAndUpdateConflictMessage (iter, true)) - // unselect this field - store.SetValue (iter, colCheckedIndex, false); - - UpdateOKButton (); - } - - void RenderPropertyName (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) - { - bool selected = (bool) store.GetValue (iter, colCheckedIndex); - string propertyName = (string) store.GetValue (iter, colPropertyNameIndex); - string error; - - CellRendererText cellRendererText = (CellRendererText) cell; - if (!selected || IsValidPropertyName (propertyName, out error)) - cellRendererText.Foreground = "black"; - else - cellRendererText.Foreground = "red"; - - cellRendererText.Text = propertyName; - } - - // @clearOnValid: clear the message label if propertyName is valid - bool CheckAndUpdateConflictMessage (TreeIter iter, bool clearOnValid) - { - return CheckAndUpdateConflictMessage ((string) store.GetValue (iter, colPropertyNameIndex), - clearOnValid); - } - - // @clearOnValid: clear the message label if propertyName is valid - bool CheckAndUpdateConflictMessage (string name, bool clearOnValid) - { - string error; - if (IsValidPropertyName (name, out error)) { - if (clearOnValid) - SetErrorMessage (null); - return true; - } else { - SetErrorMessage (error); - return false; - } - } - - void SetErrorMessage (string message) - { - if (String.IsNullOrEmpty (message)) { - labelError.Text = String.Empty; - imageError.Clear (); - } else { - labelError.Text = message; - imageError.SetFromStock (MonoDevelop.Ide.Gui.Stock.Error, IconSize.Menu); - } - } - - bool IsValidPropertyName (string name, out string error_msg) - { - // Don't allow the user to click OK unless there is a new name - if (name.Length == 0) { - error_msg = GettextCatalog.GetString ("Property name must be non-empty."); - return false; - } - foreach (IMember member in declaringType.Members) { - if (member.Name == name) { - error_msg = GettextCatalog.GetString ("Property name conflicts with an existing member name."); - return false; - } - } - error_msg = String.Empty; - return true; - } - - private void OnVisibilityEdited (object sender, EditedArgs args) - { - TreeIter iter; - if (store.GetIterFromString (out iter, args.Path)) - store.SetValue (iter, colVisibilityIndex, args.NewText); - } - - private void OnSelectedToggled (object o, ToggledArgs args) - { - TreeIter iter; - if (!store.GetIterFromString (out iter, args.Path)) - return; - - bool old_value = (bool) store.GetValue (iter, colCheckedIndex); - store.SetValue (iter, colCheckedIndex, !old_value); - - if (old_value) - SetErrorMessage (null); - else - CheckAndUpdateConflictMessage (iter, true); - UpdateOKButton (); - } - - void UpdateOKButton () - { - TreeIter iter; - if (!store.GetIterFirst (out iter)) - return; - - bool atleast_one_selected = false; - do { - bool selected = (bool) store.GetValue (iter, colCheckedIndex); - if (!selected) - continue; - - atleast_one_selected = true; - - string propertyName = (string) store.GetValue (iter, colPropertyNameIndex); - string error; - if (!IsValidPropertyName (propertyName, out error)) { - buttonOk.Sensitive = false; - return; - } - } while (store.IterNext (ref iter)); - - buttonOk.Sensitive = atleast_one_selected; - } - - private void OnReadOnlyToggled (object o, ToggledArgs args) - { - TreeIter iter; - if (store.GetIterFromString (out iter, args.Path)) { - IField ifield = (IField) store.GetValue (iter, colFieldIndex); - if (ifield.IsReadonly || ifield.IsLiteral) - return; - - bool value = (bool) store.GetValue (iter, colReadOnlyIndex); - store.SetValue (iter, colReadOnlyIndex, !value); - } - } - - void OnSelectAllClicked (object sender, EventArgs e) - { - SelectAll (true); - } - - void OnUnselectAllClicked (object sender, EventArgs e) - { - SelectAll (false); - SetErrorMessage (null); - } - - void SelectAll (bool select) - { - TreeIter iter; - if (!store.GetIterFirst (out iter)) - return; - - // clear any old error message - SetErrorMessage (null); - - bool has_error = false; - do { - if (select && !CheckAndUpdateConflictMessage (iter, false)) - has_error = true; - store.SetValue (iter, colCheckedIndex, select); - } while (store.IterNext (ref iter)); - - if (has_error) - SetErrorMessage (GettextCatalog.GetString ("One or more property names conflict with existing members of the class")); - UpdateOKButton (); - } - - void OnCancelClicked (object sender, EventArgs e) - { - ((Widget) this).Destroy (); - } - class FieldData { - public IField Field { get; set; } - public string PropertyName { get; set; } - public bool ReadOnly { get; set; } - public Modifiers Modifiers { get; set; } - - public FieldData (IField field, string propertyName, bool readOnly, Modifiers modifiers) - { - this.Field = field; - this.PropertyName = propertyName; - this.ReadOnly = readOnly; - this.Modifiers = modifiers; - } - } - - void OnOKClicked (object sender, EventArgs e) - { - TreeIter iter; - if (!store.GetIterFirst (out iter)) - return; - - List<FieldData> data = new List<FieldData> (); - - do { - bool selected = (bool) store.GetValue (iter, colCheckedIndex); - if (!selected) - continue; - - string propertyName = (string) store.GetValue (iter, colPropertyNameIndex); - string visibility = (string) store.GetValue (iter, colVisibilityIndex); - bool read_only = (bool) store.GetValue (iter, colReadOnlyIndex); - IField field = (IField) store.GetValue (iter, colFieldIndex); - Modifiers mod = Modifiers.None; - if (visibility.ToUpper () == "PUBLIC") - mod = Modifiers.Public; - if (visibility.ToUpper () == "PRIVATE") - mod = Modifiers.Private; - if (visibility.ToUpper () == "PROTECTED") - mod = Modifiers.Protected; - if (visibility.ToUpper () == "INTERNAL") - mod = Modifiers.Internal; - data.Add (new FieldData (field, propertyName, read_only, mod)); - } while (store.IterNext (ref iter)); - - var mode = new InsertionCursorEditMode (editor.Editor.Parent, CodeGenerationService.GetInsertionPoints (editor, declaringType)); - var helpWindow = new ModeHelpWindow (); - helpWindow.Shown += (s, a) => DesktopService.RemoveWindowShadow (helpWindow); - helpWindow.TransientFor = IdeApp.Workbench.RootWindow; - helpWindow.TitleText = GettextCatalog.GetString ("<b>Encapsulate Field -- Targeting</b>"); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Key</b>"), GettextCatalog.GetString ("<b>Behavior</b>"))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Up</b>"), GettextCatalog.GetString ("Move to <b>previous</b> target point."))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Down</b>"), GettextCatalog.GetString ("Move to <b>next</b> target point."))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Enter</b>"), GettextCatalog.GetString ("<b>Declare new property</b> at target point."))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Esc</b>"), GettextCatalog.GetString ("<b>Cancel</b> this refactoring."))); - mode.HelpWindow = helpWindow; - mode.CurIndex = mode.InsertionPoints.Count - 1; - int idx = -1, i = 0; - TextLocation lTextLocation = TextLocation.Empty; - foreach (IMember member in declaringType.Members) { - if (lTextLocation != member.Location && data.Any (d => d.Field.Location == member.Location)) - idx = i; - lTextLocation = member.Location; - i++; - } - if (idx >= 0) - mode.CurIndex = idx + 1; - mode.StartMode (); - mode.Exited += delegate(object s, InsertionCursorEventArgs args) { - if (args.Success) { - CodeGenerator generator = CodeGenerator.CreateGenerator (editor.Editor.Document.MimeType, editor.Editor.TabsToSpaces, editor.Editor.Options.TabSize, editor.Editor.EolMarker); - StringBuilder code = new StringBuilder (); - for (int j = 0; j < data.Count; j++) { - if (j > 0) { - code.AppendLine (); - code.AppendLine (); - } - var f = data[j]; - code.Append (generator.CreateFieldEncapsulation (declaringType, f.Field, f.PropertyName, f.Modifiers, f.ReadOnly)); - } - args.InsertionPoint.Insert (editor.Editor, code.ToString ()); - } - }; - ((Widget) this).Destroy (); - } - - static MemberAttributes StringToMemberAttributes (string visibility) - { - switch (visibility) { - case "Public": - return MemberAttributes.Public; - case "Private": - return MemberAttributes.Private; - case "Protected": - return MemberAttributes.Family; - case "Internal": - return MemberAttributes.Assembly; - default: - throw new ArgumentException ("Unknown visibility : " + visibility); - } - } - - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ExtensionMethods.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ExtensionMethods.cs deleted file mode 100644 index cb52d45e37..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ExtensionMethods.cs +++ /dev/null @@ -1,148 +0,0 @@ -// -// ExtensionMethods.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using ICSharpCode.NRefactory.CSharp.Resolver; -using MonoDevelop.Ide.Gui; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.CSharp.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.Semantics; -using System.Threading.Tasks; -using MonoDevelop.Core; -using System.Threading; -using MonoDevelop.Core.Instrumentation; -using MonoDevelop.Projects; - -namespace MonoDevelop.Refactoring -{ - public static class ExtensionMethods - { - class ResolverAnnotation - { - public CancellationTokenSource SharedTokenSource; - public Task<CSharpAstResolver> Task; - public CSharpUnresolvedFile ParsedFile; - } - - public static TimerCounter ResolveCounter = InstrumentationService.CreateTimerCounter("Resolve document", "Parsing"); - - /// <summary> - /// Returns a full C# syntax tree resolver which is shared between semantic highlighting, source analysis and refactoring. - /// For code analysis tasks this should be used instead of generating an own resolver. Only exception is if a local resolving is done using a - /// resolve navigator. - /// Note: The shared resolver is fully resolved. - /// </summary> - public static Task<CSharpAstResolver> GetSharedResolver (this Document document) - { - var parsedDocument = document.ParsedDocument; - if (parsedDocument == null || document.IsProjectContextInUpdate || document.Project != null && !(document.Project is DotNetProject)) - return null; - - var unit = parsedDocument.GetAst<SyntaxTree> (); - var parsedFile = parsedDocument.ParsedFile as CSharpUnresolvedFile; - if (unit == null || parsedFile == null) - return null; - var compilation = document.Compilation; - - var resolverAnnotation = document.Annotation<ResolverAnnotation> (); - - if (resolverAnnotation != null) { - if (resolverAnnotation.ParsedFile == parsedFile) - return resolverAnnotation.Task; - if (resolverAnnotation.SharedTokenSource != null) - resolverAnnotation.SharedTokenSource.Cancel (); - document.RemoveAnnotations<ResolverAnnotation> (); - } - - var tokenSource = new CancellationTokenSource (); - var token = tokenSource.Token; - var resolveTask = Task.Factory.StartNew (delegate { - try { - using (var timer = ResolveCounter.BeginTiming ()) { - var result = new CSharpAstResolver (compilation, unit, parsedFile); - result.ApplyNavigator (new ConstantModeResolveVisitorNavigator (ResolveVisitorNavigationMode.Resolve, null), token); - return result; - } - } catch (OperationCanceledException) { - return null; - } catch (Exception e) { - LoggingService.LogError ("Error while creating the resolver.", e); - return null; - } - }, token); - - var wrapper = resolveTask.ContinueWith (t => { - if (t.IsCanceled) - return null; - if (t.IsFaulted) { - var ex = t.Exception.Flatten ().InnerException; - if (!(ex is TaskCanceledException)) - LoggingService.LogWarning ("Exception while getting shared AST resolver.", ex); - return null; - } - return t.Result; - }, TaskContinuationOptions.ExecuteSynchronously); - - document.AddAnnotation (new ResolverAnnotation { - Task = wrapper, - ParsedFile = parsedFile, - SharedTokenSource = tokenSource - }); - - return wrapper; - } - - public sealed class ConstantModeResolveVisitorNavigator : IResolveVisitorNavigator - { - readonly ResolveVisitorNavigationMode mode; - readonly IResolveVisitorNavigator targetForResolveCalls; - - public ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode mode, IResolveVisitorNavigator targetForResolveCalls) - { - this.mode = mode; - this.targetForResolveCalls = targetForResolveCalls; - } - - ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node) - { - return mode; - } - - void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result) - { - if (targetForResolveCalls != null) - targetForResolveCalls.Resolved(node, result); - } - - void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) - { - if (targetForResolveCalls != null) - targetForResolveCalls.ProcessConversion(expression, result, conversion, targetType); - } - } - - } -}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs deleted file mode 100644 index da9a514bbb..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindDerivedClassesHandler.cs +++ /dev/null @@ -1,182 +0,0 @@ -// -// FindDerivedClassesHandler.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Components.Commands; -using MonoDevelop.Refactoring; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Ide.TypeSystem; -using System.Collections.Generic; -using System.Threading; -using MonoDevelop.Projects; -using MonoDevelop.Ide.FindInFiles; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Semantics; -using System.Threading.Tasks; -using System.Linq; -using System.Collections.Concurrent; - -namespace MonoDevelop.Refactoring -{ - public class FindDerivedClassesHandler : CommandHandler - { - public static void FindDerivedClasses (ITypeDefinition cls) - { - FindDerivedSymbols (cls, null); - } - - public static void FindDerivedMembers (IMember member) - { - var cls = member.DeclaringTypeDefinition; - if (cls == null) - return; - FindDerivedSymbols (cls, member); - } - - static void FindDerivedSymbols (ITypeDefinition cls, IMember member) - { - var solution = IdeApp.ProjectOperations.CurrentSelectedSolution; - if (solution == null) - return; - - var sourceProject = TypeSystemService.GetProject (cls); - if (sourceProject == null) - return; - - var compilations = ReferenceFinder.GetAllReferencingProjects (solution, sourceProject) - .Select (TypeSystemService.GetCompilation).Where (c => c != null).ToList (); - - using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) { - var label = member == null - ? GettextCatalog.GetString ("Searching for derived classes in solution...") - : GettextCatalog.GetString ("Searching for derived members in solution..."); - monitor.BeginTask (label, compilations.Count); - - Parallel.ForEach (compilations, comp => { - try { - SearchCompilation (monitor, comp, cls, member); - } catch (Exception ex) { - LoggingService.LogInternalError (ex); - monitor.ReportError ("Unhandled error while searching", ex); - } - monitor.Step (1); - }); - - monitor.EndTask (); - }; - } - - static void SearchCompilation (ISearchProgressMonitor monitor, ICompilation comp, ITypeDefinition cls, IMember member) - { - var importedType = comp.Import (cls); - if (importedType == null) { - return; - } - - IMember impMember = null; - if (member != null) { - impMember = comp.Import (member); - if (impMember == null) { - return; - } - } - - foreach (var derivedType in comp.MainAssembly.GetAllTypeDefinitions ()) { - if (!derivedType.IsDerivedFrom (importedType)) - continue; - IEntity result; - if (member != null) { - result = FindDerivedMember (impMember, derivedType); - if (result == null) - continue; - } - else { - result = derivedType; - } - ReportResult (monitor, result); - } - } - - static IMember FindDerivedMember (IMember importedMember, ITypeDefinition derivedType) - { - IMember derivedMember; - if (importedMember.DeclaringTypeDefinition.Kind == TypeKind.Interface) { - derivedMember = derivedType.GetMembers (null, GetMemberOptions.IgnoreInheritedMembers) - .FirstOrDefault (m => m.ImplementedInterfaceMembers.Any (im => im.Region == importedMember.Region)); - } - else { - derivedMember = InheritanceHelper.GetDerivedMember (importedMember, derivedType); - } - return derivedMember; - } - - static void ReportResult (ISearchProgressMonitor monitor, IEntity result) - { - string filename = result.Region.FileName; - if (string.IsNullOrEmpty (filename)) - return; - - var textFile = TextFileProvider.Instance.GetTextEditorData (filename); - var start = textFile.LocationToOffset (result.Region.Begin); - textFile.SearchRequest.SearchPattern = result.Name; - var sr = textFile.SearchForward (start); - if (sr != null) - start = sr.Offset; - - if (textFile.Parent == null) - textFile.Dispose (); - - monitor.ReportResult (new MemberReference (result, result.Region, start, result.Name.Length)); - } - - protected override void Run (object data) - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null) - return; - - ResolveResult resolveResult; - var item = CurrentRefactoryOperationsHandler.GetItem (doc, out resolveResult); - - var typeDef = item as ITypeDefinition; - if (typeDef != null && ((typeDef.Kind == TypeKind.Class && !typeDef.IsSealed) || typeDef.Kind == TypeKind.Interface)) { - FindDerivedClasses (typeDef); - return; - } - - var member = item as IMember; - var handler = new FindDerivedSymbolsHandler (member); - if (handler.IsValid) { - handler.Run (); - return; - } - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindExtensionMethodHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindExtensionMethodHandler.cs deleted file mode 100644 index 97e5441889..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindExtensionMethodHandler.cs +++ /dev/null @@ -1,81 +0,0 @@ -// -// FindExtensionMethodHandler.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Ide.FindInFiles; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Analysis; -using ICSharpCode.NRefactory.CSharp.Resolver; -using MonoDevelop.Ide.TypeSystem; - -namespace MonoDevelop.Refactoring -{ - class FindExtensionMethodHandler - { - //Ide.Gui.Document doc; - ITypeDefinition entity; - - public FindExtensionMethodHandler (Ide.Gui.Document doc, ITypeDefinition entity) - { - //this.doc = doc; - this.entity = entity; - } - - public void Run () - { - using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) { - foreach (var project in IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects ()) { - var comp = TypeSystemService.GetCompilation (project); - foreach (var type in comp.MainAssembly.GetAllTypeDefinitions ()) { - if (!type.IsStatic) - continue; - foreach (var method in type.GetMethods (m => m.IsStatic)) { - if (!method.IsExtensionMethod) - continue; - IType[] ifTypes; - var typeDef = comp.Import (entity); - if (typeDef == null) - continue; - if (!CSharpResolver.IsEligibleExtensionMethod (typeDef, method, true, out ifTypes)) - continue; - - var tf = TextFileProvider.Instance.GetReadOnlyTextEditorData (method.Region.FileName); - var start = tf.LocationToOffset (method.Region.Begin); - tf.SearchRequest.SearchPattern = method.Name; - var sr = tf.SearchForward (start); - if (sr != null) - start = sr.Offset; - monitor.ReportResult (new MemberReference (method, method.Region, start, method.Name.Length)); - } - } - } - } - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindMemberOverloadsHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindMemberOverloadsHandler.cs deleted file mode 100644 index db0f154683..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindMemberOverloadsHandler.cs +++ /dev/null @@ -1,77 +0,0 @@ -// -// FindMemberOverloadsHandler.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2013 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Ide.FindInFiles; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Analysis; - -namespace MonoDevelop.Refactoring -{ - class FindMemberOverloadsHandler - { - //Ide.Gui.Document doc; - IMember entity; - - public FindMemberOverloadsHandler (Ide.Gui.Document doc, IMember entity) - { - //this.doc = doc; - this.entity = entity; - } - - public bool IsValid { - get { - foreach (var overloadedMember in entity.DeclaringType.GetMembers (m => m.Name == entity.Name && m.SymbolKind == entity.SymbolKind)) { - var fileName = overloadedMember.Region.FileName; - if (string.IsNullOrEmpty (fileName)) - continue; - return true; - } - return false; - } - } - - public void Run () - { - using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) { - foreach (var overloadedMember in entity.DeclaringType.GetMembers (m => m.Name == entity.Name && m.SymbolKind == entity.SymbolKind)) { - var fileName = overloadedMember.Region.FileName; - if (string.IsNullOrEmpty (fileName)) - continue; - var tf = TextFileProvider.Instance.GetReadOnlyTextEditorData (fileName); - var start = tf.LocationToOffset (overloadedMember.Region.Begin); - tf.SearchRequest.SearchPattern = overloadedMember.Name; - var sr = tf.SearchForward (start); - if (sr != null) - start = sr.Offset; - monitor.ReportResult (new MemberReference (overloadedMember, overloadedMember.Region, start, overloadedMember.Name.Length)); - } - } - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindReferencesHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindReferencesHandler.cs deleted file mode 100644 index 8e219e7e35..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/FindReferencesHandler.cs +++ /dev/null @@ -1,107 +0,0 @@ -// -// FindReferencesHandler.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Threading; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Components.Commands; -using MonoDevelop.Core; -using MonoDevelop.Ide; -using MonoDevelop.Ide.FindInFiles; -using MonoDevelop.Refactoring; -using ICSharpCode.NRefactory.Semantics; - -namespace MonoDevelop.Refactoring -{ - public class FindReferencesHandler : CommandHandler - { - public static void FindRefs (object obj) - { - var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true); - var solution = IdeApp.ProjectOperations.CurrentSelectedSolution; - ThreadPool.QueueUserWorkItem (delegate { - try { - foreach (var mref in ReferenceFinder.FindReferences (solution, obj, false, ReferenceFinder.RefactoryScope.Unknown, monitor)) { - monitor.ReportResult (mref); - } - } catch (Exception ex) { - if (monitor != null) - monitor.ReportError ("Error finding references", ex); - else - LoggingService.LogError ("Error finding references", ex); - } finally { - if (monitor != null) - monitor.Dispose (); - } - }); - } - protected override void Run (object data) - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null) - return; - ResolveResult resolveResoult; - object item = CurrentRefactoryOperationsHandler.GetItem (doc, out resolveResoult); - if (item != null) - FindRefs (item); - } - } - - public class FindAllReferencesHandler : CommandHandler - { - public static void FindRefs (object obj) - { - var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true); - var solution = IdeApp.ProjectOperations.CurrentSelectedSolution; - ThreadPool.QueueUserWorkItem (delegate { - try { - foreach (var mref in ReferenceFinder.FindReferences (solution, obj, true, ReferenceFinder.RefactoryScope.Unknown, monitor)) { - monitor.ReportResult (mref); - } - } catch (Exception ex) { - if (monitor != null) - monitor.ReportError ("Error finding references", ex); - else - LoggingService.LogError ("Error finding references", ex); - } finally { - if (monitor != null) - monitor.Dispose (); - } - }); - } - protected override void Run (object data) - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null) - return; - ResolveResult resolveResoult; - object item = CurrentRefactoryOperationsHandler.GetItem (doc, out resolveResoult); - if (item != null) - FindRefs (item); - } - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/GotoDeclarationHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/GotoDeclarationHandler.cs deleted file mode 100644 index 58bb8a4dd0..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/GotoDeclarationHandler.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// GotoDeclarationHandler.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Components.Commands; -using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Refactoring; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.Semantics; - -namespace MonoDevelop.Refactoring -{ - public class GotoDeclarationHandler : CommandHandler - { - protected override void Run (object data) - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null) - return; - - ResolveResult resolveResoult; - object item = CurrentRefactoryOperationsHandler.GetItem (doc, out resolveResoult); - var entity = item as INamedElement; - if (entity != null) { - IdeApp.ProjectOperations.JumpToDeclaration (entity); - } else { - var v = item as IVariable; - if (v != null) - IdeApp.ProjectOperations.JumpToDeclaration (v); - } - } - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ImportSymbolHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ImportSymbolHandler.cs deleted file mode 100644 index 1a2960a688..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ImportSymbolHandler.cs +++ /dev/null @@ -1,519 +0,0 @@ -// -// RefactoryCommands.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Components.Commands; -using MonoDevelop.Projects; -using MonoDevelop.Projects.Text; -using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Ide.Gui.Dialogs; -using MonoDevelop.Ide.FindInFiles; -using MonoDevelop.Refactoring; -using MonoDevelop.Ide; -using System.Linq; -using MonoDevelop.Ide.CodeCompletion; -using Mono.TextEditor; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.CSharp.Resolver; - -namespace MonoDevelop.Refactoring -{ - class GenerateNamespaceImport - { - public bool GenerateUsing { get; set; } - public bool InsertNamespace { get; set; } - } - - class ImportSymbolCache - { - Dictionary<string, GenerateNamespaceImport> cache = new Dictionary<string, GenerateNamespaceImport> (); - - public GenerateNamespaceImport GetResult (IUnresolvedFile unit, IType type, MonoDevelop.Ide.Gui.Document doc) - { - GenerateNamespaceImport result; - if (cache.TryGetValue (type.Namespace, out result)) - return result; - result = new GenerateNamespaceImport (); - cache[type.Namespace] = result; - TextEditorData data = doc.Editor; - - result.InsertNamespace = false; - var loc = new TextLocation (data.Caret.Line, data.Caret.Column); - foreach (var ns in RefactoringOptions.GetUsedNamespaces (doc, loc)) { - if (type.Namespace == ns) { - result.GenerateUsing = false; - return result; - } - } - - result.GenerateUsing = true; - string name = type.Name; - - foreach (string ns in RefactoringOptions.GetUsedNamespaces (doc, loc)) { - if (doc.Compilation.MainAssembly.GetTypeDefinition (ns, name, type.TypeParameterCount) != null) { - result.GenerateUsing = false; - result.InsertNamespace = true; - return result; - } - } - return result; - } - } - - class ImportSymbolCompletionData : CompletionData - { - IType type; - Ambience ambience; - ParsedDocument unit; - MonoDevelop.Ide.Gui.Document doc; - ImportSymbolCache cache; - - public IType Type { - get { return this.type; } - } - - public ImportSymbolCompletionData (MonoDevelop.Ide.Gui.Document doc, ImportSymbolCache cache, IType type) - { - this.doc = doc; - this.cache = cache; -// this.data = doc.Editor; - this.ambience = AmbienceService.GetAmbience (doc.Editor.MimeType); - this.type = type; - this.unit = doc.ParsedDocument; - this.DisplayFlags |= ICSharpCode.NRefactory.Completion.DisplayFlags.IsImportCompletion; - } - - bool initialized = false; - bool generateUsing, insertNamespace; - - void Initialize () - { - if (initialized) - return; - initialized = true; - if (string.IsNullOrEmpty (type.Namespace)) - return; - var result = cache.GetResult (unit.ParsedFile, type, doc); - generateUsing = result.GenerateUsing; - insertNamespace = result.InsertNamespace; - } - - #region IActionCompletionData implementation - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) - { - Initialize (); - using (var undo = doc.Editor.OpenUndoGroup ()) { - string text = insertNamespace ? type.Namespace + "." + type.Name : type.Name; - if (text != GetCurrentWord (window)) { - if (window.WasShiftPressed && generateUsing) - text = type.Namespace + "." + text; - window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, GetCurrentWord (window), text); - } - - if (!window.WasShiftPressed && generateUsing) { - var generator = CodeGenerator.CreateGenerator (doc); - if (generator != null) { - generator.AddGlobalNamespaceImport (doc, type.Namespace); - // reparse - doc.UpdateParseDocument (); - } - } - } - ka |= KeyActions.Ignore; - } - #endregion - - #region ICompletionData implementation - public override IconId Icon { - get { - return type.GetStockIcon (); - } - } - string displayText = null; - public override string DisplayText { - get { - if (displayText == null) - displayText = ambience.GetString (type, OutputFlags.IncludeGenerics); - return displayText; - } - } - - static string GetDefaultDisplaySelection (string description, bool isSelected) - { - if (!isSelected) - return "<span foreground=\"darkgray\">" + description + "</span>"; - return description; - } - - string displayDescription = null; - public override string GetDisplayDescription (bool isSelected) - { - if (displayDescription == null) { - Initialize (); - if (generateUsing || insertNamespace) { - displayDescription = string.Format (GettextCatalog.GetString ("(from '{0}')"), type.Namespace); - } else { - displayDescription = ""; - } - } - return GetDefaultDisplaySelection (displayDescription, isSelected); - } - - - public override string Description { - get { - Initialize (); - if (generateUsing) - return string.Format (GettextCatalog.GetString ("Add namespace import '{0}'"), type.Namespace); - return null; - } - } - - public override string CompletionText { - get { - return type.Name; - } - } - #endregion - } - - public class ImportSymbolHandler: CommandHandler - { - protected override void Run () - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null || doc.ParsedDocument == null) - return; - ITextEditorExtension ext = doc.EditorExtension; - while (ext != null && !(ext is CompletionTextEditorExtension)) - ext = ext.Next; - if (ext == null) - return; - - var dom = doc.Compilation; - ImportSymbolCache cache = new ImportSymbolCache (); - var lookup = new MemberLookup (null, doc.Compilation.MainAssembly); - - List<ImportSymbolCompletionData> typeList = new List<ImportSymbolCompletionData> (); - foreach (var type in dom.GetTopLevelTypeDefinitons ()) { - if (!lookup.IsAccessible (type, false)) - continue; - typeList.Add (new ImportSymbolCompletionData (doc, cache, type)); - } - - typeList.Sort (delegate (ImportSymbolCompletionData left, ImportSymbolCompletionData right) { - return left.Type.Name.CompareTo (right.Type.Name); - }); - - - CompletionDataList completionList = new CompletionDataList (); - completionList.IsSorted = true; - typeList.ForEach (cd => completionList.Add (cd)); - - ((CompletionTextEditorExtension)ext).ShowCompletion (completionList); - } - } -} - -/* -// -// RefactoryCommands.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2010 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Components.Commands; -using MonoDevelop.Projects; -using MonoDevelop.Projects.Text; -using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Ide.Gui.Dialogs; -using MonoDevelop.Ide.FindInFiles; -using MonoDevelop.Refactoring; -using MonoDevelop.Ide; -using System.Linq; -using MonoDevelop.Ide.CodeCompletion; -using Mono.TextEditor; -using ICSharpCode.NRefactory.TypeSystem; -using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.CSharp.Resolver; -using MonoDevelop.Ide.TypeSystem; - -namespace MonoDevelop.Refactoring -{ - class GenerateNamespaceImport - { - public bool GenerateUsing { get; set; } - public bool InsertNamespace { get; set; } - } - - class ImportSymbolCache - { - Dictionary<string, GenerateNamespaceImport> cache = new Dictionary<string, GenerateNamespaceImport> (); - - public GenerateNamespaceImport GetResult (IUnresolvedFile unit, string typeNamespace, string typeName, MonoDevelop.Ide.Gui.Document doc) - { - GenerateNamespaceImport result; - if (cache.TryGetValue (typeNamespace, out result)) - return result; - result = new GenerateNamespaceImport (); - cache[typeNamespace] = result; - TextEditorData data = doc.Editor; - - result.InsertNamespace = false; - var loc = new TextLocation (data.Caret.Line, data.Caret.Column); - foreach (var ns in RefactoringOptions.GetUsedNamespaces (doc, loc)) { - if (typeNamespace == ns) { - result.GenerateUsing = false; - return result; - } - } - - result.GenerateUsing = true; - string name = typeName; - - foreach (string ns in RefactoringOptions.GetUsedNamespaces (doc, loc)) { - if (doc.Compilation.MainAssembly.GetTypeDefinition (ns, name, 0) != null) { - result.GenerateUsing = false; - result.InsertNamespace = true; - return result; - } - } - return result; - } - } - - class ImportSymbolCompletionData : CompletionData - { - internal readonly string typeName; - ParsedDocument unit; - MonoDevelop.Ide.Gui.Document doc; - ImportSymbolCache cache; - TypeKind kind; - Lazy<FrameworkLookup.AssemblyLookup> lookup; - MonoDevelop.Projects.ProjectReference reference; - public ImportSymbolCompletionData (MonoDevelop.Ide.Gui.Document doc, ImportSymbolCache cache, string typeName, TypeKind kind, Lazy<FrameworkLookup.AssemblyLookup> lookup, MonoDevelop.Projects.ProjectReference reference) - { - this.doc = doc; - this.cache = cache; - this.unit = doc.ParsedDocument; - this.kind = kind; - this.typeName = typeName; - this.lookup = lookup; - this.reference = reference; - } - - bool initialized = false; - bool generateReference; - bool generateUsing; - bool insertNamespace; - - void Initialize () - { - if (initialized) - return; - initialized = true; - var netProject = (DotNetProject)doc.Project; - generateReference = true; - foreach (var r in netProject.References) { - if (r.Equals (reference)) { - generateReference = false; - break; - } - } - var result = cache.GetResult (unit.ParsedFile, lookup.Value.Namespace, typeName, doc); - generateUsing = result.GenerateUsing; - insertNamespace = result.InsertNamespace; - } - - #region IActionCompletionData implementation - public override void InsertCompletionText (CompletionListWindow window, ref KeyActions ka, Gdk.Key closeChar, char keyChar, Gdk.ModifierType modifier) - { - Initialize (); - string text = insertNamespace ? lookup.Value.Namespace + "." + typeName : typeName; - if (text != GetCurrentWord (window)) { - if (window.WasShiftPressed && generateReference) - text = lookup.Value.Namespace + "." + text; - window.CompletionWidget.SetCompletionText (window.CodeCompletionContext, GetCurrentWord (window), text); - } - - if (generateReference) { - var project = doc.Project; - project.Items.Add (reference); - IdeApp.ProjectOperations.Save (project); - } - - if (!window.WasShiftPressed && generateUsing) { - var generator = CodeGenerator.CreateGenerator (doc); - if (generator != null) { - generator.AddGlobalNamespaceImport (doc, lookup.Value.Namespace); - // reparse - doc.UpdateParseDocument (); - } - } - } - #endregion - - #region ICompletionData implementation - public override IconId Icon { - get { - switch (kind) { - case TypeKind.Delegate: - return MonoDevelop.Ide.Gui.Stock.Delegate; - case TypeKind.Struct: - return MonoDevelop.Ide.Gui.Stock.Struct; - case TypeKind.Interface: - return MonoDevelop.Ide.Gui.Stock.Interface; - case TypeKind.Enum: - return MonoDevelop.Ide.Gui.Stock.Enum; - default: - return MonoDevelop.Ide.Gui.Stock.Class; - } - } - } - - public override string DisplayText { - get { - return typeName; - } - } - - string displayDescription = null; - public override string DisplayDescription { - get { - if (displayDescription == null) { - Initialize (); - if (generateReference) { - displayDescription = string.Format (GettextCatalog.GetString ("(reference '{0}')"), reference.Reference); - } else if (generateUsing) { - displayDescription = string.Format (GettextCatalog.GetString ("(from '{0}')"), lookup.Value.Namespace); - } else { - displayDescription = ""; - } - } - return displayDescription; - } - } - - public override string Description { - get { - return DisplayDescription; - } - } - - public override string CompletionText { - get { - return typeName; - } - } - #endregion - } - - public class ImportSymbolHandler: CommandHandler - { - protected override void Run () - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null || doc.ParsedDocument == null) - return; - ITextEditorExtension ext = doc.EditorExtension; - while (ext != null && !(ext is CompletionTextEditorExtension)) - ext = ext.Next; - if (ext == null) - return; - - var dom = doc.Compilation; - ImportSymbolCache cache = new ImportSymbolCache (); - List<ImportSymbolCompletionData> typeList = new List<ImportSymbolCompletionData> (); - Dictionary<string, MonoDevelop.Projects.ProjectReference> referenceCache = new Dictionary<string, MonoDevelop.Projects.ProjectReference> (); - var netProject = (DotNetProject)doc.Project; - foreach (var type in TypeSystemService.GetFrameworkLookup (netProject).GetAllTypes ()) { - var r = type.Item3.Value; - MonoDevelop.Projects.ProjectReference reference; - if (!referenceCache.TryGetValue (r.FullName, out reference)) { - var systemAssembly = netProject.AssemblyContext.GetAssemblyFromFullName (r.FullName, r.Package, netProject.TargetFramework); - if (systemAssembly == null) { - reference = null; - } else { - reference = new MonoDevelop.Projects.ProjectReference (systemAssembly); - } - referenceCache [r.FullName] = reference; - } - if (reference == null) - continue; - typeList.Add (new ImportSymbolCompletionData (doc, cache, type.Item2, type.Item1, type.Item3, reference)); - } - - typeList.Sort (delegate (ImportSymbolCompletionData left, ImportSymbolCompletionData right) { - return left.typeName.CompareTo (right.typeName); - }); - - - var completionList = new CompletionDataList (); - completionList.IsSorted = true; - - typeList.ForEach (cd => completionList.Add (cd)); - - ((CompletionTextEditorExtension)ext).ShowCompletion (completionList); - } - } -} - * */ diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/InsertionPointService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/InsertionPointService.cs new file mode 100644 index 0000000000..04409ab3af --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/InsertionPointService.cs @@ -0,0 +1,253 @@ +// +// InsertionPointService.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Ide.TypeSystem; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using MonoDevelop.Ide.Editor; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using ICSharpCode.NRefactory6.CSharp; + +namespace MonoDevelop.Refactoring +{ + public static class InsertionPointService + { + public static List<InsertionPoint> GetInsertionPoints (IReadonlyTextDocument data, ParsedDocument parsedDocument, ITypeSymbol type, Location part) + { + if (data == null) + throw new ArgumentNullException (nameof (data)); + if (parsedDocument == null) + throw new ArgumentNullException (nameof (parsedDocument)); + if (type == null) + throw new ArgumentNullException (nameof (type)); + if (!type.IsDefinedInSource ()) + throw new ArgumentException ("The given type needs to be defined in source code.", nameof (type)); + + // update type from parsed document, since this is always newer. + //type = parsedDocument.GetInnermostTypeDefinition (type.GetLocation ()) ?? type; + List<InsertionPoint> result = new List<InsertionPoint> (); + int offset = part.SourceSpan.Start; + if (offset < 0) + return result; + while (offset < data.Length && data.GetCharAt (offset) != '{') { + offset++; + } + var realStartLocation = data.OffsetToLocation (offset); + + result.Add (GetInsertionPosition (data, realStartLocation.Line, realStartLocation.Column)); + result [0].LineBefore = NewLineInsertion.None; + + var declaringType = type.DeclaringSyntaxReferences.FirstOrDefault (dsr => dsr.SyntaxTree.FilePath == part.SourceTree.FilePath && dsr.Span.Contains (part.SourceSpan)); + if (declaringType == null) + return result; + foreach (var member in type.GetMembers ()) { + if (member.IsImplicitlyDeclared || !member.IsDefinedInSource()) + continue; +
+ //var domLocation = member.BodyRegion.End; + foreach (var loc in member.DeclaringSyntaxReferences) { + if (loc.SyntaxTree.FilePath != part.SourceTree.FilePath || !declaringType.Span.Contains (part.SourceSpan)) + continue; + var domLocation = data.OffsetToLocation (loc.Span.End); + + if (domLocation.Line <= 0) { + var lineSegment = data.GetLineByOffset (loc.Span.Start); + if (lineSegment == null) + continue; + domLocation = new DocumentLocation (lineSegment.LineNumber, lineSegment.Length + 1); + } + result.Add (GetInsertionPosition (data, domLocation.Line, domLocation.Column)); + break; + } + } + + result [result.Count - 1].LineAfter = NewLineInsertion.None; + CheckStartPoint (data, result [0], result.Count == 1); + if (result.Count > 1) { + result.RemoveAt (result.Count - 1); + NewLineInsertion insertLine; + var typeSyntaxReference = type.DeclaringSyntaxReferences.FirstOrDefault (r => r.Span.Contains (part.SourceSpan)); + + var lineBefore = data.GetLineByOffset (typeSyntaxReference.Span.End).PreviousLine; + if (lineBefore != null && lineBefore.Length == lineBefore.GetIndentation (data).Length) { + insertLine = NewLineInsertion.None; + } else { + insertLine = NewLineInsertion.Eol; + } + // search for line start + var line = data.GetLineByOffset (typeSyntaxReference.Span.End); + int col = typeSyntaxReference.Span.End - line.Offset; + if (line != null) { + var lineOffset = line.Offset; + col = Math.Min (line.Length, col); + while (lineOffset + col - 2 >= 0 && col > 1 && char.IsWhiteSpace (data.GetCharAt (lineOffset + col - 2))) + col--; + } + Console.WriteLine ("add 1"); + result.Add (new InsertionPoint (new DocumentLocation (line.LineNumber, col), insertLine, NewLineInsertion.Eol)); + CheckEndPoint (data, result [result.Count - 1], result.Count == 1); + } + +// foreach (var region in parsedDocument.UserRegions.Where (r => type.BodyRegion.IsInside (r.Region.Begin))) { +// result.Add (new InsertionPoint (new DocumentLocation (region.Region.BeginLine + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol)); +// result.Add (new InsertionPoint (new DocumentLocation (region.Region.EndLine, 1), NewLineInsertion.Eol, NewLineInsertion.Eol)); +// result.Add (new InsertionPoint (new DocumentLocation (region.Region.EndLine + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol)); +// } + result.Sort ((left, right) => left.Location.CompareTo (right.Location)); + // foreach (var res in result) + // Console.WriteLine (res); + return result; + } + + static void CheckEndPoint (IReadonlyTextDocument doc, InsertionPoint point, bool isStartPoint) + { + var line = doc.GetLine (point.Location.Line); + if (line == null) + return; + + if (doc.GetLineIndent (line).Length + 1 < point.Location.Column) + point.LineBefore = NewLineInsertion.BlankLine; + if (point.Location.Column < line.Length + 1) + point.LineAfter = NewLineInsertion.Eol; + } + + static void CheckStartPoint (IReadonlyTextDocument doc, InsertionPoint point, bool isEndPoint) + { + var line = doc.GetLine (point.Location.Line); + if (line == null) + return; + if (doc.GetLineIndent (line).Length + 1 == point.Location.Column) { + int lineNr = point.Location.Line; + while (lineNr > 1 && doc.GetLineIndent (lineNr - 1).Length == doc.GetLine (lineNr - 1).Length) { + lineNr--; + } + line = doc.GetLine (lineNr); + point.Location = new DocumentLocation (lineNr, doc.GetLineIndent (line).Length + 1); + } + + if (doc.GetLineIndent (line).Length + 1 < point.Location.Column) + point.LineBefore = NewLineInsertion.Eol; + if (point.Location.Column < line.Length + 1) + point.LineAfter = isEndPoint ? NewLineInsertion.Eol : NewLineInsertion.BlankLine; + } + + static InsertionPoint GetInsertionPosition (IReadonlyTextDocument doc, int line, int column) + { + int bodyEndOffset = doc.LocationToOffset (line, column) + 1; + var curLine = doc.GetLine (line); + if (curLine != null) { + if (bodyEndOffset < curLine.Offset + curLine.Length) { + // case1: positition is somewhere inside the start line + return new InsertionPoint (new DocumentLocation (line, column + 1), NewLineInsertion.Eol, NewLineInsertion.BlankLine); + } + } + + // -> if position is at line end check next line + var nextLine = doc.GetLine (line + 1); + if (nextLine == null) // check for 1 line case. + return new InsertionPoint (new DocumentLocation (line, column + 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine); + + for (int i = nextLine.Offset; i < nextLine.EndOffset; i++) { + char ch = doc.GetCharAt (i); + if (!char.IsWhiteSpace (ch)) { + // case2: next line contains non ws chars. + return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.BlankLine); + } + } + + var nextLine2 = doc.GetLine (line + 2); + if (nextLine2 != null) { + for (int i = nextLine2.Offset; i < nextLine2.EndOffset; i++) { + char ch = doc.GetCharAt (i); + if (!char.IsWhiteSpace (ch)) { + // case3: one blank line + return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol); + } + } + } + // case4: more than 1 blank line + return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.None); + } + + internal static InsertionPoint GetSuitableInsertionPoint (IReadonlyTextDocument data, IEnumerable<InsertionPoint> points, ITypeSymbol cls, Location part, SyntaxNode member) + { + switch (member.Kind ()) { + case SyntaxKind.FieldDeclaration: + return GetNewFieldPosition (data, points, cls, part); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ConstructorDeclaration: + case SyntaxKind.DestructorDeclaration: + case SyntaxKind.OperatorDeclaration: + return GetNewMethodPosition (data, points, cls, part); + case SyntaxKind.EventDeclaration: + return GetNewEventPosition (data, points, cls, part); + case SyntaxKind.PropertyDeclaration: + return GetNewPropertyPosition (data, points, cls, part); + } + throw new InvalidOperationException ("Invalid member type: " + member.Kind ()); + } + + static InsertionPoint GetNewFieldPosition (IReadonlyTextDocument data, IEnumerable<InsertionPoint> points, ITypeSymbol cls, Location part) + { + if (!cls.GetMembers ().OfType<IFieldSymbol> ().Any ()) + return points.FirstOrDefault (); + var lastField = cls.GetMembers ().OfType<IFieldSymbol> ().Last (); + var begin = data.OffsetToLocation (lastField.Locations.First ().SourceSpan.Start); + return points.FirstOrDefault (p => p.Location > begin); + } + + static InsertionPoint GetNewMethodPosition (IReadonlyTextDocument data, IEnumerable<InsertionPoint> points, ITypeSymbol cls, Location part) + { + if (!cls.GetMembers ().OfType<IMethodSymbol> ().Any ()) + return GetNewPropertyPosition (data, points, cls, part); + var lastMethod = cls.GetMembers ().OfType<IMethodSymbol> ().Last (); + var begin = data.OffsetToLocation (lastMethod.Locations.First ().SourceSpan.Start); + return points.FirstOrDefault (p => p.Location > begin); + } + + static InsertionPoint GetNewPropertyPosition (IReadonlyTextDocument data, IEnumerable<InsertionPoint> points, ITypeSymbol cls, Location part) + { + if (!cls.GetMembers ().OfType<IPropertySymbol> ().Any ()) + return GetNewFieldPosition (data, points, cls, part); + var lastProperty = cls.GetMembers ().OfType<IPropertySymbol> ().Last (); + var begin = data.OffsetToLocation (lastProperty.Locations.First ().SourceSpan.Start); + return points.FirstOrDefault (p => p.Location > begin); + } + + static InsertionPoint GetNewEventPosition (IReadonlyTextDocument data, IEnumerable<InsertionPoint> points, ITypeSymbol cls, Location part) + { + if (!cls.GetMembers ().OfType<IEventSymbol> ().Any ()) + return GetNewMethodPosition (data, points, cls, part); + var lastEvent = cls.GetMembers ().OfType<IEventSymbol> ().Last (); + var begin = data.OffsetToLocation (lastEvent.Locations.First ().SourceSpan.Start); + return points.FirstOrDefault (p => p.Location > begin); + } + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/OverridesImplementsDialog.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/OverridesImplementsDialog.cs deleted file mode 100644 index bc8541afc5..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/OverridesImplementsDialog.cs +++ /dev/null @@ -1,400 +0,0 @@ -// OverridesImplementsDialog.cs -// -//Author: -// Ankit Jain <jankit@novell.com> -// -// Copyright (c) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// -// - -using System; -using System.Collections.Generic; - -using Gtk; - -using MonoDevelop.Core; -using MonoDevelop.Projects.CodeGeneration; -using MonoDevelop.Projects.Dom; -using MonoDevelop.Projects.Dom.Output; -using Ambience_ = MonoDevelop.Projects.Dom.Output.Ambience; -using MonoDevelop.Ide; -using System.Text; -using Mono.TextEditor; -using Mono.TextEditor.PopupWindow; - - -namespace MonoDevelop.Refactoring -{ - partial class OverridesImplementsDialog : Gtk.Dialog - { - IType cls; - TreeStore store; - CodeRefactorer refactorer; - Ambience ambience; - MonoDevelop.Ide.Gui.Document editor; - - private const int colCheckedIndex = 0; - private const int colIconIndex = 1; - private const int colNameIndex = 2; - private const int colExplicitIndex = 3; - private const int colItemIndex = 4; - -/* private const OutputFlags default_conversion_flags = - OutputFlags.ShowParameterNames | - OutputFlags.ShowGenericParameters | - OutputFlags.ShowReturnType | - OutputFlags.ShowParameters | - OutputFlags.UseIntrinsicTypeNames;*/ - private const OutputFlags default_conversion_flags = - OutputFlags.IncludeParameters | - OutputFlags.IncludeParameterName | - OutputFlags.IncludeReturnType; - - public OverridesImplementsDialog (MonoDevelop.Ide.Gui.Document editor, IType cls) - { - this.Build(); - this.editor = editor; - this.cls = cls; - - // FIXME: title - Title = GettextCatalog.GetString ("Override and/or implement members"); - - store = new TreeStore (typeof (bool), typeof (Gdk.Pixbuf), typeof (string), typeof (bool), typeof (IMember)); - - // Column #1 - TreeViewColumn nameCol = new TreeViewColumn (); - nameCol.Title = GettextCatalog.GetString ("Name"); - nameCol.Expand = true; - nameCol.Resizable = true; - - CellRendererToggle cbRenderer = new CellRendererToggle (); - cbRenderer.Activatable = true; - cbRenderer.Toggled += OnSelectToggled; - nameCol.PackStart (cbRenderer, false); - nameCol.AddAttribute (cbRenderer, "active", colCheckedIndex); - - CellRendererPixbuf iconRenderer = new CellRendererPixbuf (); - nameCol.PackStart (iconRenderer, false); - nameCol.AddAttribute (iconRenderer, "pixbuf", colIconIndex); - - CellRendererText nameRenderer = new CellRendererText (); - nameRenderer.Ellipsize = Pango.EllipsizeMode.End; - nameCol.PackStart (nameRenderer, true); - nameCol.AddAttribute (nameRenderer, "text", colNameIndex); - - treeview.AppendColumn (nameCol); - - // Column #2 - CellRendererToggle explicitRenderer = new CellRendererToggle (); - explicitRenderer.Activatable = true; - explicitRenderer.Xalign = 0.0f; - explicitRenderer.Toggled += OnExplicitToggled; - TreeViewColumn explicitCol = new TreeViewColumn (); - explicitCol.Title = GettextCatalog.GetString ("Explicit"); - explicitCol.PackStart (explicitRenderer, true); - explicitCol.SetCellDataFunc (explicitRenderer, new TreeCellDataFunc (RenderExplicitCheckbox)); - explicitCol.AddAttribute (explicitRenderer, "active", colExplicitIndex); - treeview.AppendColumn (explicitCol); - - store.SetSortColumnId (colNameIndex, SortType.Ascending); - treeview.Model = store; - - buttonCancel.Clicked += OnCancelClicked; - buttonOk.Clicked += OnOKClicked; - buttonSelectAll.Clicked += delegate { SelectAll (true); }; - buttonUnselectAll.Clicked += delegate { SelectAll (false); }; - - refactorer = IdeApp.Workspace.GetCodeRefactorer (IdeApp.ProjectOperations.CurrentSelectedSolution); - ambience = AmbienceService.GetAmbienceForFile (cls.GetDefinition ().Region.FileName); - PopulateTreeView (); - UpdateOKButton (); - } - - void PopulateTreeView () - { - List<IMember> class_members = new List<IMember> (); - List<IMember> interface_members = new List<IMember> (); - - refactorer.FindOverridables (cls, class_members, interface_members, false, true); - - Dictionary<string, TreeIter> iter_cache = new Dictionary<string,TreeIter> (); - PopulateTreeView (class_members, iter_cache, - ImageService.GetPixbuf (MonoDevelop.Ide.Gui.Stock.Class, IconSize.Menu)); - PopulateTreeView (interface_members, iter_cache, - ImageService.GetPixbuf (MonoDevelop.Ide.Gui.Stock.Interface, IconSize.Menu)); - } - - void PopulateTreeView (List<IMember> members, Dictionary<string, TreeIter> iter_cache, Gdk.Pixbuf parent_icon) - { - foreach (IMember member in members) { - TreeIter iter; - if (!iter_cache.TryGetValue (member.DeclaringType.FullName, out iter)) { - iter = store.AppendValues (false, parent_icon, - GetDescriptionString (member.DeclaringType), false, member.DeclaringType); - iter_cache [member.DeclaringType.FullName] = iter; - } - - store.AppendValues (iter, false, - ImageService.GetPixbuf (member.StockIcon, IconSize.Menu), - GetDescriptionString (member), false, member); - } - } - -#region Event handlers - void RenderExplicitCheckbox (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) - { - CellRendererToggle cellToggle = (CellRendererToggle) cell; - IMember item = (IMember) store.GetValue (iter, colItemIndex); - bool parent_is_class = false; - - // Don't show 'explicit' checkbox for Class/interface rows or class methods - TreeIter parentIter; - if (item is IMember && store.IterParent (out parentIter, iter)) { - IType parentClass = store.GetValue (parentIter, colItemIndex) as IType; - if (parentClass != null && parentClass.ClassType != ClassType.Interface) - parent_is_class = true; - } - - if (parent_is_class || item is IType) { - cellToggle.Visible = false; - } else { - cellToggle.Visible = true; - cellToggle.Active = GetExplicit (iter); - } - } - - void OnSelectToggled (object o, ToggledArgs args) - { - TreeIter iter; - if (!store.GetIterFromString (out iter, args.Path)) - return; - - bool old_value = GetChecked (iter); - store.SetValue (iter, colCheckedIndex, !old_value); - - TreeIter parent; - if (store.IterParent (out parent, iter)) { - // Member(method/property/etc) row clicked - // Set the parent's 'checked' state according to the children's state - bool all_children_checked = true; - foreach (TreeIter child in GetAllNodes (parent, false)) { - if (!GetChecked (child)) { - all_children_checked = false; - break; - } - } - - store.SetValue (parent, colCheckedIndex, all_children_checked); - } else { - // Mark children's state to match parent's checked state - foreach (TreeIter child in GetAllNodes (iter, false)) - store.SetValue (child, colCheckedIndex, !old_value); - } - UpdateOKButton (); - } - - void OnExplicitToggled (object o, ToggledArgs args) - { - TreeIter iter; - if (!store.GetIterFromString (out iter, args.Path)) - return; - - store.SetValue (iter, colExplicitIndex, !GetExplicit (iter)); - } - - void OnCancelClicked (object sender, EventArgs e) - { - ((Widget) this).Destroy (); - } - - void UpdateOKButton () - { - bool atleast_one_checked = false; - foreach (TreeIter iter in GetAllNodes (TreeIter.Zero, true)) { - if (GetChecked (iter)) { - atleast_one_checked = true; - break; - } - } - buttonOk.Sensitive = atleast_one_checked; - } - - void OnOKClicked (object sender, EventArgs e) - { - try { - StringBuilder code = new StringBuilder (); - CodeGenerator generator = CodeGenerator.CreateGenerator (editor.Editor.Document.MimeType, editor.Editor.TabsToSpaces, editor.Editor.Options.TabSize, editor.Editor.EolMarker); - IType declaringType = editor.GetType (cls.Location.Line, cls.Location.Column) ?? cls; - - foreach (KeyValuePair<IType, IEnumerable<TreeIter>> kvp in GetAllClasses ()) { - if (code.Length > 0) { - code.AppendLine (); - code.AppendLine (); - } - - //update the target class so that new members don't get inserted in weird locations - StringBuilder curImpl = new StringBuilder (); - foreach (var pair in YieldImpls (kvp)) { - if (curImpl.Length > 0) { - curImpl.AppendLine (); - curImpl.AppendLine (); - } - curImpl.Append (generator.CreateMemberImplementation (declaringType, pair.Key, pair.Value != null).Code); - } - if (kvp.Key.ClassType == ClassType.Interface) { - code.Append (generator.WrapInRegions (kvp.Key.Name + " implementation", curImpl.ToString ())); - } else { - code.Append (curImpl.ToString ()); - } - } - - var mode = new InsertionCursorEditMode (editor.Editor.Parent, CodeGenerationService.GetInsertionPoints (editor, this.cls)); - var helpWindow = new ModeHelpWindow (); - helpWindow.Shown += (s, a) => DesktopService.RemoveWindowShadow (helpWindow); - helpWindow.TransientFor = IdeApp.Workbench.RootWindow; - helpWindow.TitleText = GettextCatalog.GetString ("<b>Override -- Targeting</b>"); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Key</b>"), GettextCatalog.GetString ("<b>Behavior</b>"))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Up</b>"), GettextCatalog.GetString ("Move to <b>previous</b> target point."))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Down</b>"), GettextCatalog.GetString ("Move to <b>next</b> target point."))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Enter</b>"), GettextCatalog.GetString ("<b>Declare overrides</b> at target point."))); - helpWindow.Items.Add (new KeyValuePair<string, string> (GettextCatalog.GetString ("<b>Esc</b>"), GettextCatalog.GetString ("<b>Cancel</b> this refactoring."))); - mode.HelpWindow = helpWindow; - mode.CurIndex = mode.InsertionPoints.Count - 1; - mode.StartMode (); - mode.Exited += delegate(object s, InsertionCursorEventArgs args) { - if (args.Success) - args.InsertionPoint.Insert (editor.Editor, code.ToString ()); - }; - - } finally { - ((Widget) this).Destroy (); - } - } -#endregion - -#region Helper methods - - IEnumerable<KeyValuePair<IType, IEnumerable<TreeIter>>> GetAllClasses () - { - TreeIter iter; - if (!store.GetIterFirst (out iter)) - yield break; - do { - TreeIter firstMember; - if (store.IterChildren (out firstMember, iter)) { - List<TreeIter> children = new List<TreeIter> (GetCheckedSiblings (firstMember)); - if (children.Count > 0) - yield return new KeyValuePair<IType, IEnumerable<TreeIter>> ( - (IType) store.GetValue (iter, colItemIndex), - children); - } - } while (store.IterNext (ref iter)); - } - - IEnumerable<TreeIter> GetCheckedSiblings (TreeIter firstMember) - { - TreeIter iter = firstMember; - do { - if (GetChecked (iter)) { - yield return iter; - } - } while (store.IterNext (ref iter)); - } - - IEnumerable<KeyValuePair<IMember, IReturnType>> YieldImpls (KeyValuePair<IType, IEnumerable<TreeIter>> kvp) - { - bool is_interface = kvp.Key.ClassType == ClassType.Interface; - IReturnType privateImplementationType = new DomReturnType (kvp.Key.FullName); - foreach (TreeIter memberIter in kvp.Value) { - yield return new KeyValuePair<IMember, IReturnType> ( - GetIMember (memberIter), - (is_interface && GetExplicit (memberIter)) ? privateImplementationType : null); - } - } - - void SelectAll (bool select) - { - foreach (TreeIter iter in GetAllNodes (TreeIter.Zero, true)) - store.SetValue (iter, colCheckedIndex, select); - UpdateOKButton (); - } - - bool GetChecked (TreeIter iter) - { - return (bool) store.GetValue (iter, colCheckedIndex); - } - - IMember GetIMember (TreeIter iter) - { - return (IMember) store.GetValue (iter, colItemIndex); - } - - bool GetExplicit (TreeIter iter) - { - return (bool) store.GetValue (iter, colExplicitIndex); - } - - IEnumerable<TreeIter> GetAllNodes (TreeIter parent, bool iter_children) - { - TreeIter child; - if (parent.Equals (TreeIter.Zero)) { - if (!store.IterChildren (out child)) - yield break; - } else if (!store.IterChildren (out child, parent)) { - yield break; - } - - do { - yield return child; - if (iter_children && store.IterHasChild (child)) { - TreeIter iter; - if (store.IterChildren (out iter, child)) { - do { - yield return iter; - } while (store.IterNext (ref iter)); - } - } - } while (store.IterNext (ref child)); - } - - string GetDescriptionString (IType klass) - { - return String.Format ("{0} ({1})", ambience.GetString (klass, default_conversion_flags), klass.Namespace); - } - - string GetDescriptionString (IMember member) - { - string sig = null; - OutputFlags flags = default_conversion_flags & ~OutputFlags.IncludeReturnType; - - sig = ambience.GetString (member, flags); - - if (sig == null) - throw new InvalidOperationException (String.Format ("Unsupported language member type: {0}", member.GetType ())); - - return sig + " : " + ambience.GetString (member.ReturnType, default_conversion_flags); - } - -#endregion - - } - -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringOperation.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringOperation.cs deleted file mode 100644 index 444970df71..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringOperation.cs +++ /dev/null @@ -1,74 +0,0 @@ -// -// RefactoringOperation.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; -using MonoDevelop.Core; -using MonoDevelop.Ide; -using ICSharpCode.NRefactory.CSharp.Refactoring; - -namespace MonoDevelop.Refactoring -{ - public abstract class RefactoringOperation - { - public string Name { - get; - set; - } - - public bool IsBreakingAPI { - get; - set; - } - - public virtual string AccelKey { - get { - return ""; - } - } - public virtual string GetMenuDescription (RefactoringOptions options) - { - return Name; - } - - public virtual bool IsValid (RefactoringOptions options) - { - return true; - } - - public virtual List<Change> PerformChanges (RefactoringOptions options, object properties) - { - throw new System.NotImplementedException (); - } - - public virtual void Run (RefactoringOptions options) - { - var changes = PerformChanges (options, null); - var monitor = IdeApp.Workbench.ProgressMonitors.GetBackgroundProgressMonitor (Name, null); - RefactoringService.AcceptChanges (monitor, changes); - } - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringOptions.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringOptions.cs index f0f9af2e6b..b1532d9e50 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringOptions.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringOptions.cs @@ -28,36 +28,32 @@ using MonoDevelop.Ide.Gui; using System.Text; using MonoDevelop.Projects.Text; -using ICSharpCode.NRefactory.CSharp; using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.CSharp.Resolver; using MonoDevelop.Core; using MonoDevelop.Ide.TypeSystem; -using System.Collections.Generic; -using System.Linq; -using ICSharpCode.NRefactory.Semantics; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.CSharp.TypeSystem; +using MonoDevelop.Ide.Editor; using System.Threading.Tasks; +using System.Collections.Immutable; +using System.Threading; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis; namespace MonoDevelop.Refactoring { public class RefactoringOptions { - readonly Task<CSharpAstResolver> resolver; - - public Document Document { + public TextEditor Editor { get; private set; } - - public object SelectedItem { + + public DocumentContext DocumentContext { get; - set; + private set; } - - public ResolveResult ResolveResult { + + public object SelectedItem { get; set; } @@ -70,43 +66,48 @@ namespace MonoDevelop.Refactoring public string MimeType { get { - return DesktopService.GetMimeTypeForUri (Document.FileName); + return DesktopService.GetMimeTypeForUri (DocumentContext.Name); } } - public TextLocation Location { + public DocumentLocation Location { get { - return new TextLocation (Document.Editor.Caret.Line, Document.Editor.Caret.Column); + return Editor.CaretLocation; } } - //public readonly SyntaxTree Unit; + public RefactoringOptions () { } - public RefactoringOptions (Document doc) + public RefactoringOptions (MonoDevelop.Ide.Gui.Document doc) : this(doc.Editor, doc) { - this.Document = doc; - if (doc != null && doc.ParsedDocument != null) { + } + + public RefactoringOptions (TextEditor editor, DocumentContext doc) + { + this.DocumentContext = doc; + this.Editor = editor; + /*if (doc != null && doc.ParsedDocument != null) { var sharedResolver = doc.GetSharedResolver (); if (sharedResolver == null) return; resolver = sharedResolver; //Unit = resolver != null ? resolver.RootNode as SyntaxTree : null; - } + }*/ } - public Mono.TextEditor.TextEditorData GetTextEditorData () + public TextEditor GetTextEditorData () { - return Document.Editor; + return Editor; } - public static string GetWhitespaces (Document document, int insertionOffset) + public static string GetWhitespaces (TextEditor editor, int insertionOffset) { StringBuilder result = new StringBuilder (); - for (int i = insertionOffset; i < document.Editor.Length; i++) { - char ch = document.Editor.GetCharAt (i); + for (int i = insertionOffset; i < editor.Length; i++) { + char ch = editor.GetCharAt (i); if (ch == ' ' || ch == '\t') { result.Append (ch); } else { @@ -115,96 +116,56 @@ namespace MonoDevelop.Refactoring } return result.ToString (); } - - public string OutputNode (AstNode node) - { - using (var stringWriter = new System.IO.StringWriter ()) { - var formatter = new TextWriterTokenWriter (stringWriter); -// formatter.Indentation = indentLevel; - stringWriter.NewLine = Document.Editor.EolMarker; - - var visitor = new CSharpOutputVisitor (formatter, FormattingOptionsFactory.CreateMono ()); - node.AcceptVisitor (visitor); - return stringWriter.ToString (); - } - } - - public CodeGenerator CreateCodeGenerator () - { - var result = CodeGenerator.CreateGenerator (Document); - if (result == null) - LoggingService.LogError ("Generator can't be generated for : " + Document.Editor.MimeType); - return result; - } - - public static string GetIndent (Document document, IEntity member) + + public static string GetIndent (TextEditor editor, Microsoft.CodeAnalysis.SyntaxNode member) { - return GetWhitespaces (document, document.Editor.Document.LocationToOffset (member.Region.BeginLine, 1)); + return GetWhitespaces (editor, member.SpanStart); } public string GetWhitespaces (int insertionOffset) { - return GetWhitespaces (Document, insertionOffset); - } - - public string GetIndent (IEntity member) - { - return GetIndent (Document, member); - } -// -// public IReturnType ShortenTypeName (IReturnType fullyQualifiedTypeName) -// { -// return Document.ParsedDocument.CompilationUnit.ShortenTypeName (fullyQualifiedTypeName, Document.Editor.Caret.Line, Document.Editor.Caret.Column); -// } -// -// public ParsedDocument ParseDocument () -// { -// return ProjectDomService.Parse (Dom.Project, Document.FileName, Document.Editor.Text); -// } - - public List<string> GetUsedNamespaces () - { - return GetUsedNamespaces (Document, Location); - } - - public static List<string> GetUsedNamespaces (Document doc, TextLocation loc) - { - var result = new List<string> (); - var pf = doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile; - if (pf == null) - return result; - var scope = pf.GetUsingScope (loc); - if (scope == null) - return result; - var resolver = pf.GetResolver (doc.Compilation, loc); - for (var n = scope; n != null; n = n.Parent) { - result.Add (n.NamespaceName); - result.AddRange (n.Usings.Select (u => u.ResolveNamespace (resolver)) - .Where (nr => nr != null) - .Select (nr => nr.FullName)); - } - return result; + return GetWhitespaces (Editor, insertionOffset); } - public ResolveResult Resolve (AstNode node) + public Task<ImmutableArray<string>> GetUsedNamespacesAsync (CancellationToken cancellationToken = default (CancellationToken)) { - if (!resolver.IsCompleted) - resolver.Wait (2000); - if (!resolver.IsCompleted) - return null; - return resolver.Result.Resolve (node); + return GetUsedNamespacesAsync (Editor, DocumentContext, Editor.LocationToOffset (Location)); } - public AstType CreateShortType (IType fullType) + public static async Task<ImmutableArray<string>> GetUsedNamespacesAsync (TextEditor editor, DocumentContext doc, int offset, CancellationToken cancellationToken = default (CancellationToken)) { - var parsedFile = Document.ParsedDocument.ParsedFile as CSharpUnresolvedFile; + if (editor == null) + throw new System.ArgumentNullException ("editor"); + var parsedDocument = doc.ParsedDocument; + if (parsedDocument == null) + return ImmutableArray<string>.Empty; + var result = ImmutableArray<string>.Empty.ToBuilder (); + var sm = parsedDocument.GetAst<SemanticModel> (); + var node = sm.SyntaxTree.GetRoot ().FindNode (TextSpan.FromBounds (offset, offset)); - var csResolver = parsedFile.GetResolver (Document.Compilation, Document.Editor.Caret.Location); + while (node != null) { + var cu = node as CompilationUnitSyntax; + if (cu != null) { + foreach (var u in cu.Usings) { + if (u.Kind () == Microsoft.CodeAnalysis.CSharp.SyntaxKind.UsingDirective) + result.Add (u.Name.ToString ()); + } + } + var ns = node as NamespaceDeclarationSyntax; + if (ns != null) { + var name = ns.Name.ToString (); + result.Add (name); + foreach (var u in ns.Usings) { + if (u.Kind () == Microsoft.CodeAnalysis.CSharp.SyntaxKind.UsingDirective) + result.Add (u.Name.ToString ()); + } + } + + node = node.Parent; + } - var builder = new ICSharpCode.NRefactory.CSharp.Refactoring.TypeSystemAstBuilder (csResolver); - return builder.ConvertType (fullType); + return result.ToImmutable (); } - // public List<string> GetResolveableNamespaces (RefactoringOptions options, out bool resolveDirect) // { diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs index 0f98ee8010..fe722b16b4 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringPreviewDialog.cs @@ -30,10 +30,10 @@ using Gtk; using Gdk; using MonoDevelop.Core; -using Mono.TextEditor; using MonoDevelop.Ide; -using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.Components; +using MonoDevelop.Ide.Editor; +using MonoDevelop.Core.Text; using MonoDevelop.Ide.Fonts; @@ -48,9 +48,9 @@ namespace MonoDevelop.Refactoring const int objColumn = 2; const int statusVisibleColumn = 3; - List<Change> changes; + IList<Change> changes; - public RefactoringPreviewDialog (List<Change> changes) + public RefactoringPreviewDialog (IList<Change> changes) { this.Build (); this.changes = changes; @@ -107,9 +107,9 @@ namespace MonoDevelop.Refactoring return; } - Mono.TextEditor.TextDocument doc = new Mono.TextEditor.TextDocument (); - doc.Text = Mono.TextEditor.Utils.TextFileUtility.ReadAllText (replaceChange.FileName); - DocumentLocation loc = doc.OffsetToLocation (replaceChange.Offset); + var doc = TextEditorFactory.CreateNewDocument (); + doc.Text = TextFileUtility.ReadAllText (replaceChange.FileName); + var loc = doc.OffsetToLocation (replaceChange.Offset); string text = string.Format (GettextCatalog.GetString ("(Line:{0}, Column:{1})"), loc.Line, loc.Column); if (treeviewPreview.Selection.IterIsSelected (iter)) { @@ -136,21 +136,21 @@ namespace MonoDevelop.Refactoring return; var openDocument = IdeApp.Workbench.GetDocument (replaceChange.FileName); - Mono.TextEditor.TextDocument originalDocument = new Mono.TextEditor.TextDocument (); + var originalDocument = TextEditorFactory.CreateNewDocument (); originalDocument.FileName = replaceChange.FileName; if (openDocument == null) { - originalDocument.Text = Mono.TextEditor.Utils.TextFileUtility.ReadAllText (replaceChange.FileName); + originalDocument.Text = TextFileUtility.ReadAllText (replaceChange.FileName); } else { - originalDocument.Text = openDocument.Editor.Document.Text; + originalDocument.Text = openDocument.Editor.Text; } - Mono.TextEditor.TextDocument changedDocument = new Mono.TextEditor.TextDocument (); + var changedDocument = TextEditorFactory.CreateNewDocument (); changedDocument.FileName = replaceChange.FileName; changedDocument.Text = originalDocument.Text; - changedDocument.Replace (replaceChange.Offset, replaceChange.RemovedChars, replaceChange.InsertedText); - - string diffString = Mono.TextEditor.Utils.Diff.GetDiffString (originalDocument, changedDocument); + changedDocument.ReplaceText (replaceChange.Offset, replaceChange.RemovedChars, replaceChange.InsertedText); + + string diffString = originalDocument.GetDiffAsString (changedDocument); cellRendererDiff.InitCell (treeviewPreview, true, diffString, replaceChange.FileName); } catch (Exception e) { diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs index d45cbe97cb..4f4009a77e 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringService.cs @@ -33,106 +33,22 @@ using MonoDevelop.Core; using MonoDevelop.Ide.Gui; using System.Linq; using MonoDevelop.AnalysisCore; -using ICSharpCode.NRefactory; using System.Threading.Tasks; using System.Threading; using MonoDevelop.CodeActions; using MonoDevelop.CodeIssues; -using Mono.TextEditor; using MonoDevelop.Ide.TypeSystem; using System.Diagnostics; using MonoDevelop.Core.Instrumentation; +using MonoDevelop.Ide.Editor; namespace MonoDevelop.Refactoring { public static class RefactoringService { - static readonly List<RefactoringOperation> refactorings = new List<RefactoringOperation>(); - static readonly List<CodeActionProvider> contextActions = new List<CodeActionProvider> (); - static readonly List<CodeIssueProvider> inspectors = new List<CodeIssueProvider> (); - - public static IEnumerable<CodeActionProvider> ContextAddinNodes { - get { - return contextActions; - } - } - - public static void AddProvider (CodeActionProvider provider) - { - contextActions.Add (provider); - } - - public static void AddProvider (CodeIssueProvider provider) - { - inspectors.Add (provider); - } - - public static List<CodeIssueProvider> Inspectors { - get { - return inspectors; - } - } - static RefactoringService () { - AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Refactoring/Refactorings", delegate(object sender, ExtensionNodeEventArgs args) { - switch (args.Change) { - case ExtensionChange.Add: - refactorings.Add ((RefactoringOperation)args.ExtensionObject); - break; - case ExtensionChange.Remove: - refactorings.Remove ((RefactoringOperation)args.ExtensionObject); - break; - } - }); - - AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Refactoring/CodeActions", delegate(object sender, ExtensionNodeEventArgs args) { - switch (args.Change) { - case ExtensionChange.Add: - contextActions.Add (((CodeActionAddinNode)args.ExtensionNode).Action); - break; - case ExtensionChange.Remove: - contextActions.Remove (((CodeActionAddinNode)args.ExtensionNode).Action); - break; - } - }); - - AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Refactoring/CodeActionSource", delegate(object sender, ExtensionNodeEventArgs args) { - switch (args.Change) { - case ExtensionChange.Add: - contextActions.AddRange (((ICodeActionProviderSource)args.ExtensionObject).GetProviders ()); - break; - } - }); - - AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Refactoring/CodeIssues", delegate(object sender, ExtensionNodeEventArgs args) { - switch (args.Change) { - case ExtensionChange.Add: - inspectors.Add (((CodeIssueAddinNode)args.ExtensionNode).Inspector); - break; - case ExtensionChange.Remove: - inspectors.Remove (((CodeIssueAddinNode)args.ExtensionNode).Inspector); - break; - } - }); - - AddinManager.AddExtensionNodeHandler ("/MonoDevelop/Refactoring/CodeIssueSource", delegate(object sender, ExtensionNodeEventArgs args) { - switch (args.Change) { - case ExtensionChange.Add: - var source = (ICodeIssueProviderSource)args.ExtensionObject; - var providers = source.GetProviders (); - inspectors.AddRange (providers); - break; - } - }); - - } - - public static IEnumerable<RefactoringOperation> Refactorings { - get { - return refactorings; - } } class RenameHandler @@ -156,14 +72,14 @@ namespace MonoDevelop.Refactoring } } - public static void AcceptChanges (ProgressMonitor monitor, List<Change> changes) + public static void AcceptChanges (ProgressMonitor monitor, IList<Change> changes) { AcceptChanges (monitor, changes, MonoDevelop.Ide.TextFileProvider.Instance); } - public static void AcceptChanges (ProgressMonitor monitor, List<Change> changes, MonoDevelop.Projects.Text.ITextFileProvider fileProvider) + public static void AcceptChanges (ProgressMonitor monitor, IList<Change> changes, MonoDevelop.Ide.ITextFileProvider fileProvider) { - var rctx = new RefactoringOptions (null); + var rctx = new RefactoringOptions (null, null); var handler = new RenameHandler (changes); FileService.FileRenamed += handler.FileRename; var fileNames = new HashSet<FilePath> (); @@ -193,145 +109,54 @@ namespace MonoDevelop.Refactoring FileService.FileRenamed -= handler.FileRename; TextReplaceChange.FinishRefactoringOperation (); } - - public static IEnumerable<CodeIssueProvider> GetInspectors (string mimeType) - { - return inspectors.Where (i => i.MimeType == mimeType); - } - - static Stopwatch validActionsWatch = new Stopwatch (); - static Stopwatch actionWatch = new Stopwatch (); - public static IEnumerable<CodeAction> GetValidActions (Document doc, TextLocation loc, CancellationToken cancellationToken = default (CancellationToken)) +// public static void QueueQuickFixAnalysis (Document doc, TextLocation loc, CancellationToken token, Action<List<CodeAction>> callback) +// { +// var ext = doc.GetContent<MonoDevelop.AnalysisCore.Gui.ResultsEditorExtension> (); +// var issues = ext != null ? ext.GetResultsAtOffset (doc.Editor.LocationToOffset (loc), token).OrderBy (r => r.Level).ToList () : new List<Result> (); +// +// ThreadPool.QueueUserWorkItem (delegate { +// try { +// var result = new List<CodeAction> (); +// foreach (var r in issues) { +// if (token.IsCancellationRequested) +// return; +// var fresult = r as FixableResult; +// if (fresult == null) +// continue; +//// foreach (var action in FixOperationsHandler.GetActions (doc, fresult)) { +//// result.Add (new AnalysisContextActionProvider.AnalysisCodeAction (action, r) { +//// DocumentRegion = action.DocumentRegion +//// }); +//// } +// } +// result.AddRange (GetValidActions (doc, loc).Result); +// callback (result); +// } catch (Exception ex) { +// LoggingService.LogError ("Error in analysis service", ex); +// } +// }); +// } + + public static MonoDevelop.Ide.Editor.DocumentLocation GetCorrectResolveLocation (IReadonlyTextDocument editor, MonoDevelop.Ide.Editor.DocumentLocation location) { - var editor = doc.Editor; - string disabledNodes = editor != null ? PropertyService.Get ("ContextActions." + editor.MimeType, "") ?? "" : ""; - var result = new List<CodeAction> (); - var timer = InstrumentationService.CreateTimerCounter ("Source analysis background task", "Source analysis"); - timer.BeginTiming (); - validActionsWatch.Restart (); - var timeTable = new Dictionary<CodeActionProvider, long> (); - try { - var parsedDocument = doc.ParsedDocument; - if (editor != null && parsedDocument != null && parsedDocument.CreateRefactoringContext != null) { - var ctx = parsedDocument.CreateRefactoringContext (doc, cancellationToken); - if (ctx != null) { - foreach (var provider in contextActions.Where (fix => - fix.MimeType == editor.MimeType && - disabledNodes.IndexOf (fix.IdString, StringComparison.Ordinal) < 0)) - { - try { - actionWatch.Restart (); - result.AddRange (provider.GetActions (doc, ctx, loc, cancellationToken)); - actionWatch.Stop (); - timeTable[provider] = actionWatch.ElapsedMilliseconds; - } catch (Exception ex) { - LoggingService.LogError ("Error in context action provider " + provider.Title, ex); - } - } - } - } - } catch (Exception ex) { - LoggingService.LogError ("Error in analysis service", ex); - } finally { - timer.EndTiming (); - validActionsWatch.Stop (); - if (validActionsWatch.ElapsedMilliseconds > 1000) { - LoggingService.LogWarning ("Warning slow edit action update."); - foreach (var pair in timeTable) { - if (pair.Value > 50) - LoggingService.LogInfo ("ACTION '" + pair.Key.Title + "' took " + pair.Value +"ms"); - } - } - } - return (IEnumerable<CodeAction>)result; - } - - public static void QueueQuickFixAnalysis (Document doc, TextLocation loc, CancellationToken token, Action<List<CodeAction>> callback) - { - var ext = doc.GetContent<MonoDevelop.AnalysisCore.Gui.ResultsEditorExtension> (); - var issues = ext != null ? ext.GetResultsAtOffset (doc.Editor.LocationToOffset (loc), token).OrderBy (r => r.Level).ToList () : new List<Result> (); - - ThreadPool.QueueUserWorkItem (delegate { - try { - var result = new List<CodeAction> (); - foreach (var r in issues) { - if (token.IsCancellationRequested) - return; - var fresult = r as FixableResult; - if (fresult == null) - continue; - foreach (var action in FixOperationsHandler.GetActions (doc, fresult)) { - result.Add (new AnalysisContextActionProvider.AnalysisCodeAction (action, r) { - DocumentRegion = action.DocumentRegion - }); - } - } - result.AddRange (GetValidActions (doc, loc)); - callback (result); - } catch (Exception ex) { - LoggingService.LogError ("Error in analysis service", ex); - } - }); - } - - public static IList<CodeAction> ApplyFixes (IEnumerable<CodeAction> fixes, IRefactoringContext refactoringContext) - { - if (fixes == null) - throw new ArgumentNullException ("fixes"); - if (refactoringContext == null) - throw new ArgumentNullException ("refactoringContext"); - var allFixes = fixes as IList<CodeAction> ?? fixes.ToArray (); - if (allFixes.Count == 0) - return new List<CodeAction> (); - - var scriptProvider = refactoringContext as IRefactoringContext; - if (scriptProvider == null) { - return RunAll (allFixes, refactoringContext, null); - } - using (var script = scriptProvider.CreateScript ()) { - return RunAll (allFixes, refactoringContext, script); - } - } - - public static void ApplyFix (CodeAction action, IRefactoringContext context) - { - using(var script = context.CreateScript ()) { - action.Run (context, script); - } - } - - static List<CodeAction> RunAll (IEnumerable<CodeAction> allFixes, IRefactoringContext refactoringContext, object script) - { - var appliedFixes = new List<CodeAction> (); - foreach (var fix in allFixes) { - fix.Run (refactoringContext, script); - appliedFixes.Add (fix); - } - return appliedFixes; - } - - public static DocumentLocation GetCorrectResolveLocation (Document doc, DocumentLocation location) - { - if (doc == null) - return location; - var editor = doc.Editor; if (editor == null || location.Column == 1) return location; - if (editor.IsSomethingSelected) - return editor.MainSelection.Start; - + /*if (editor is TextEditor) { + if (((TextEditor)editor).IsSomethingSelected) + return ((TextEditor)editor).SelectionRegion.Begin; + }*/ var line = editor.GetLine (location.Line); if (line == null || location.Column > line.LengthIncludingDelimiter) return location; int offset = editor.LocationToOffset (location); - if (offset > 0 && !char.IsLetterOrDigit (doc.Editor.GetCharAt (offset)) && char.IsLetterOrDigit (doc.Editor.GetCharAt (offset - 1))) - return new DocumentLocation (location.Line, location.Column - 1); + if (offset > 0 && !char.IsLetterOrDigit (editor.GetCharAt (offset)) && char.IsLetterOrDigit (editor.GetCharAt (offset - 1))) + return new MonoDevelop.Ide.Editor.DocumentLocation (location.Line, location.Column - 1); return location; } - static readonly CodeAnalysisBatchRunner runner = new CodeAnalysisBatchRunner(); + //static readonly CodeAnalysisBatchRunner runner = new CodeAnalysisBatchRunner(); /// <summary> /// Queues a code analysis job. @@ -340,11 +165,12 @@ namespace MonoDevelop.Refactoring /// <param name="progressMessage"> /// The message used for a progress monitor, or null if no progress monitor should be used. /// </param> - public static IJobContext QueueCodeIssueAnalysis(IAnalysisJob job, string progressMessage = null) - { - if (progressMessage != null) - job = new ProgressMonitorWrapperJob (job, progressMessage); - return runner.QueueJob (job); - } +// public static IJobContext QueueCodeIssueAnalysis(IAnalysisJob job, string progressMessage = null) +// { +// if (progressMessage != null) +// job = new ProgressMonitorWrapperJob (job, progressMessage); +// return runner.QueueJob (job); +// return null; +// } } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringSymbolInfo.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringSymbolInfo.cs new file mode 100644 index 0000000000..2305f274a3 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoringSymbolInfo.cs @@ -0,0 +1,96 @@ +// +// RefactoringSymbolInfo.cs +// +// Author: +// Mike Krüger <mkrueger@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using MonoDevelop.Core; +using MonoDevelop.Ide.Gui; +using MonoDevelop.Components.Commands; +using MonoDevelop.Refactoring; +using MonoDevelop.Ide; +using Microsoft.CodeAnalysis; +using System.Collections.Immutable; +using System.Threading.Tasks; +using MonoDevelop.Ide.Editor; +using System.Threading; +using System; +using Microsoft.CodeAnalysis.CSharp; + +namespace MonoDevelop.Refactoring +{ + + class RefactoringSymbolInfo + { + public readonly static RefactoringSymbolInfo Empty = new RefactoringSymbolInfo(new SymbolInfo()); + + SymbolInfo symbolInfo; + + public ISymbol Symbol { + get { + return symbolInfo.Symbol; + } + } + + public ImmutableArray<ISymbol> CandidateSymbols { + get { + return symbolInfo.CandidateSymbols; + } + } + + public ISymbol DeclaredSymbol { + get; + internal set; + } + + public RefactoringSymbolInfo (SymbolInfo symbolInfo) + { + this.symbolInfo = symbolInfo; + } + + public static async Task<RefactoringSymbolInfo> GetSymbolInfoAsync (DocumentContext document, int offset, CancellationToken cancellationToken = default(CancellationToken)) + { + if (document == null) + throw new ArgumentNullException ("document"); + if (document.ParsedDocument == null) + return RefactoringSymbolInfo.Empty; + var unit = document.ParsedDocument.GetAst<SemanticModel> (); + if (unit != null) { + var root = await unit.SyntaxTree.GetRootAsync (cancellationToken).ConfigureAwait (false); + try { + var token = root.FindToken (offset); + if (!token.Span.IntersectsWith (offset)) + return RefactoringSymbolInfo.Empty; + var symbol = unit.GetSymbolInfo (token.Parent); + return new RefactoringSymbolInfo (symbol) { + DeclaredSymbol = token.IsKind (SyntaxKind.IdentifierToken) ? unit.GetDeclaredSymbol (token.Parent) : null + }; + } catch (Exception) { + return RefactoringSymbolInfo.Empty; + } + } + return RefactoringSymbolInfo.Empty; + } + } + +} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs deleted file mode 100644 index 1dd79118c7..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/RefactoryCommands.cs +++ /dev/null @@ -1,441 +0,0 @@ -// -// RefactoryCommands.cs -// -// Author: -// Lluis Sanchez Gual -// -// Copyright (C) 2006 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; - -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Components.Commands; -using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Ide.FindInFiles; -using MonoDevelop.Ide; -using System.Linq; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.TypeSystem; -using Mono.TextEditor; -using ICSharpCode.NRefactory.Semantics; -using MonoDevelop.CodeActions; -using MonoDevelop.SourceEditor.QuickTasks; -using MonoDevelop.Projects; -using MonoDevelop.Ide.Gui.Components; -using System.Threading; -using System.Threading.Tasks; - -namespace MonoDevelop.Refactoring -{ - public enum RefactoryCommands - { - CurrentRefactoryOperations, - GotoDeclaration, // in 'referenced' in IdeViMode.cs as string - FindReferences, - FindAllReferences, - FindDerivedClasses, - DeclareLocal, - RemoveUnusedImports, - SortImports, - RemoveSortImports, - ExtractMethod, - CreateMethod, - IntroduceConstant, - IntegrateTemporaryVariable, - ImportSymbol, - QuickFix, - Resolve - } - - public class CurrentRefactoryOperationsHandler : CommandHandler - { - protected override void Run (object data) - { - var del = (System.Action) data; - if (del != null) - del (); - } - - public static ResolveResult GetResolveResult (MonoDevelop.Ide.Gui.Document doc) - { - ITextEditorResolver textEditorResolver = doc.GetContent<ITextEditorResolver> (); - if (textEditorResolver != null) - return textEditorResolver.GetLanguageItem (doc.Editor.IsSomethingSelected ? doc.Editor.SelectionRange.Offset : doc.Editor.Caret.Offset); - return null; - } - - public static object GetItem (MonoDevelop.Ide.Gui.Document doc, out ResolveResult resolveResult) - { - resolveResult = GetResolveResult (doc); - if (resolveResult is LocalResolveResult) - return ((LocalResolveResult)resolveResult).Variable; - if (resolveResult is MemberResolveResult) - return ((MemberResolveResult)resolveResult).Member; - if (resolveResult is MethodGroupResolveResult) { - var mg = ((MethodGroupResolveResult)resolveResult); - var method = mg.Methods.FirstOrDefault (); - if (method == null && mg.GetExtensionMethods ().Any ()) - method = mg.GetExtensionMethods ().First ().FirstOrDefault (); - return method; - } - if (resolveResult is TypeResolveResult) - return resolveResult.Type; - if (resolveResult is NamespaceResolveResult) - return ((NamespaceResolveResult)resolveResult).Namespace; - if (resolveResult is OperatorResolveResult) - return ((OperatorResolveResult)resolveResult).UserDefinedOperatorMethod; - return null; - } - - class JumpTo - { - object el; - - public JumpTo (object el) - { - this.el = el; - } - - public void Run () - { - if (el is IUnresolvedEntity) { - var e = (IUnresolvedEntity)el; - IdeApp.Workbench.OpenDocument (e.Region.FileName, e.Region.BeginLine, e.Region.BeginColumn); - return; - } - if (el is IVariable) - IdeApp.ProjectOperations.JumpToDeclaration ((IVariable)el); - if (el is INamedElement) - IdeApp.ProjectOperations.JumpToDeclaration ((INamedElement)el); - } - } - - - class GotoBase - { - IEntity item; - - public GotoBase (IEntity item) - { - this.item = item; - } - - public void Run () - { - var cls = item as ITypeDefinition; - if (cls != null && cls.DirectBaseTypes != null) { - foreach (var bt in cls.DirectBaseTypes) { - var def = bt.GetDefinition (); - if (def != null && def.Kind != TypeKind.Interface) { - IdeApp.ProjectOperations.JumpToDeclaration (def); - return; - } - } - } - - var method = item as IMember; - if (method != null) { - var baseMethod = InheritanceHelper.GetBaseMember (method); - if (baseMethod != null) { - IdeApp.ProjectOperations.JumpToDeclaration (baseMethod); - } - return; - } - } - } - - class FindRefs - { - object obj; - bool allOverloads; - public FindRefs (object obj, bool all) - { - this.obj = obj; - this.allOverloads = all; - } - - public void Run () - { - if (allOverloads) { - FindAllReferencesHandler.FindRefs (obj); - } else { - FindReferencesHandler.FindRefs (obj); - } - } - } - - class FindDerivedClasses - { - ITypeDefinition type; - - public FindDerivedClasses (ITypeDefinition type) - { - this.type = type; - } - - public void Run () - { - FindDerivedClassesHandler.FindDerivedClasses (type); - } - } - - class RefactoringDocumentInfo - { - public IEnumerable<CodeAction> validActions; - public MonoDevelop.Ide.TypeSystem.ParsedDocument lastDocument; - - public override string ToString () - { - return string.Format ("[RefactoringDocumentInfo: #validActions={0}, lastDocument={1}]", validActions != null ? validActions.Count ().ToString () : "null", lastDocument); - } - } - - - DocumentLocation lastLocation; - - static bool HasOverloads (Solution solution, object item) - { - var member = item as IMember; - if (member != null && member.ImplementedInterfaceMembers.Any ()) - return true; - var method = item as IMethod; - if (method == null) - return false; - return method.DeclaringType.GetMethods (m => m.Name == method.Name).Count () > 1; - } - - - protected override void Update (CommandArrayInfo ainfo) - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null) - return; - - var parsedDocument = doc.ParsedDocument; - if (parsedDocument == null || parsedDocument.IsInvalid) - return; - - ResolveResult resolveResult; - object item = GetItem (doc, out resolveResult); - bool added = false; - - var options = new RefactoringOptions (doc) { - ResolveResult = resolveResult, - SelectedItem = item - }; - - var ciset = new CommandInfoSet (); - ciset.Text = GettextCatalog.GetString ("Refactor"); - - bool canRename; - if (item is IVariable || item is IParameter) { - canRename = true; - } else if (item is ITypeDefinition) { - canRename = !((ITypeDefinition)item).Region.IsEmpty; - } else if (item is IType) { - canRename = ((IType)item).Kind == TypeKind.TypeParameter; - } else if (item is IMember) { - canRename = !((IMember)item).Region.IsEmpty; - } else if (item is INamespace) { - canRename = true; - } else { - canRename = false; - } - if (canRename) { - ciset.CommandInfos.Add (IdeApp.CommandService.GetCommandInfo (MonoDevelop.Ide.Commands.EditCommands.Rename), new Action (delegate { - new MonoDevelop.Refactoring.Rename.RenameHandler ().Start (null); - })); - added = true; - } - - foreach (var refactoring in RefactoringService.Refactorings) { - if (refactoring.IsValid (options)) { - CommandInfo info = new CommandInfo (refactoring.GetMenuDescription (options)); - info.AccelKey = refactoring.AccelKey; - ciset.CommandInfos.Add (info, new Action (new RefactoringOperationWrapper (refactoring, options).Operation)); - } - } - var refactoringInfo = doc.Annotation<RefactoringDocumentInfo> (); - if (refactoringInfo == null) { - refactoringInfo = new RefactoringDocumentInfo (); - doc.AddAnnotation (refactoringInfo); - } - var loc = doc.Editor.Caret.Location; - bool first = true; - if (refactoringInfo.lastDocument != doc.ParsedDocument || loc != lastLocation) { - try { - refactoringInfo.validActions = RefactoringService.GetValidActions (doc, loc, new CancellationTokenSource (500).Token); - } catch (TaskCanceledException) { - } catch (AggregateException ae) { - ae.Flatten ().Handle (x => x is TaskCanceledException); - } - - lastLocation = loc; - refactoringInfo.lastDocument = doc.ParsedDocument; - } - if (refactoringInfo.validActions != null && refactoringInfo.lastDocument != null && refactoringInfo.lastDocument.CreateRefactoringContext != null) { - var context = refactoringInfo.lastDocument.CreateRefactoringContext (doc, CancellationToken.None); - - foreach (var fix_ in refactoringInfo.validActions.OrderByDescending (i => Tuple.Create (CodeActionEditorExtension.IsAnalysisOrErrorFix(i), (int)i.Severity, CodeActionEditorExtension.GetUsage (i.IdString)))) { - if (CodeActionEditorExtension.IsAnalysisOrErrorFix (fix_)) - continue; - var fix = fix_; - if (first) { - first = false; - if (ciset.CommandInfos.Count > 0) - ciset.CommandInfos.AddSeparator (); - } - - ciset.CommandInfos.Add (fix.Title, new Action (() => RefactoringService.ApplyFix (fix, context))); - } - } - - if (ciset.CommandInfos.Count > 0) { - ainfo.Add (ciset, null); - added = true; - } - - if (IdeApp.ProjectOperations.CanJumpToDeclaration (item)) { - var type = item as IType; - if (type != null && type.GetDefinition ().Parts.Count > 1) { - var declSet = new CommandInfoSet (); - declSet.Text = GettextCatalog.GetString ("_Go to Declaration"); - var ct = type.GetDefinition (); - foreach (var part in ct.Parts) - declSet.CommandInfos.Add (string.Format (GettextCatalog.GetString ("{0}, Line {1}"), FormatFileName (part.Region.FileName), part.Region.BeginLine), new System.Action (new JumpTo (part).Run)); - ainfo.Add (declSet); - } else { - ainfo.Add (IdeApp.CommandService.GetCommandInfo (RefactoryCommands.GotoDeclaration), new System.Action (new JumpTo (item).Run)); - } - added = true; - } - - if (item is IMember) { - var member = (IMember)item; - if (member.IsOverride || member.ImplementedInterfaceMembers.Any ()) { - ainfo.Add (GettextCatalog.GetString ("Go to _Base Symbol"), new System.Action (new GotoBase (member).Run)); - added = true; - } - } - - if (!(item is IMethod && ((IMethod)item).SymbolKind == SymbolKind.Operator) && (item is IEntity || item is ITypeParameter || item is IVariable || item is INamespace)) { - - ainfo.Add (IdeApp.CommandService.GetCommandInfo (RefactoryCommands.FindReferences), new System.Action (new FindRefs (item, false).Run)); - if (doc.HasProject && HasOverloads (doc.Project.ParentSolution, item)) - ainfo.Add (IdeApp.CommandService.GetCommandInfo (RefactoryCommands.FindAllReferences), new System.Action (new FindRefs (item, true).Run)); - added = true; - } - - if (item is IMember) { - var member = (IMember)item; - var handler = new FindDerivedSymbolsHandler (member); - if (handler.IsValid) { - var a = ainfo.Add (GettextCatalog.GetString ("Find Derived Symbols"), new Action (handler.Run)); - a.AccelKey = IdeApp.CommandService.GetCommandInfo (RefactoryCommands.FindDerivedClasses).AccelKey; - added = true; - } - } - if (item is IMember) { - var member = (IMember)item; - if (member.SymbolKind == SymbolKind.Method || member.SymbolKind == SymbolKind.Indexer) { - var findMemberOverloadsHandler = new FindMemberOverloadsHandler (doc, member); - if (findMemberOverloadsHandler.IsValid) { - ainfo.Add (GettextCatalog.GetString ("Find Member Overloads"), new System.Action (findMemberOverloadsHandler.Run)); - added = true; - } - } - } - - if (item is ITypeDefinition) { - ITypeDefinition cls = (ITypeDefinition)item; - foreach (var bc in cls.DirectBaseTypes) { - if (bc != null && bc.GetDefinition () != null && bc.GetDefinition ().Kind != TypeKind.Interface/* TODO: && IdeApp.ProjectOperations.CanJumpToDeclaration (bc)*/) { - ainfo.Add (GettextCatalog.GetString ("Go to _Base"), new System.Action (new GotoBase ((ITypeDefinition)item).Run)); - break; - } - } - if ((cls.Kind == TypeKind.Class && !cls.IsSealed) || cls.Kind == TypeKind.Interface) { - var label = cls.Kind != TypeKind.Interface ? GettextCatalog.GetString ("Find _derived classes") : GettextCatalog.GetString ("Find _implementor classes"); - var a = ainfo.Add (label, new System.Action (new FindDerivedClasses (cls).Run)); - a.AccelKey = IdeApp.CommandService.GetCommandInfo (RefactoryCommands.FindDerivedClasses).AccelKey; - } - ainfo.Add (GettextCatalog.GetString ("Find Extension Methods"), new System.Action (new FindExtensionMethodHandler (doc, cls).Run)); - added = true; - - } - - if (added) - ainfo.AddSeparator (); - } - - - class RefactoringOperationWrapper - { - RefactoringOperation refactoring; - RefactoringOptions options; - - public RefactoringOperationWrapper (RefactoringOperation refactoring, RefactoringOptions options) - { - this.refactoring = refactoring; - this.options = options; - } - - public void Operation () - { - refactoring.Run (options); - } - } - - bool IsModifiable (object member) - { - IType t = member as IType; - if (t != null) - return t.GetDefinition ().Region.FileName == IdeApp.Workbench.ActiveDocument.FileName; - if (member is IMember) - return ((IMember)member).DeclaringTypeDefinition.Region.FileName == IdeApp.Workbench.ActiveDocument.FileName; - return false; - } - - static string FormatFileName (string fileName) - { - if (fileName == null) - return null; - char[] seperators = { System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar }; - int idx = fileName.LastIndexOfAny (seperators); - if (idx > 0) - idx = fileName.LastIndexOfAny (seperators, idx - 1); - if (idx > 0) - return "..." + fileName.Substring (idx); - return fileName; - } - - public static bool ContainsAbstractMembers (IType cls) - { - if (cls == null) - return false; - return cls.GetMembers ().Any (m => m.IsAbstract); - } - } -} diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ResolveCommandHandler.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ResolveCommandHandler.cs deleted file mode 100644 index 97ab500655..0000000000 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring/ResolveCommandHandler.cs +++ /dev/null @@ -1,578 +0,0 @@ -// -// ResolveCommand.cs -// -// Author: -// Mike Krüger <mkrueger@xamarin.com> -// -// Copyright (c) 2012 Xamarin Inc. (http://xamarin.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.Text; - -using MonoDevelop.Core; -using MonoDevelop.Ide.Gui; -using MonoDevelop.Components.Commands; -using MonoDevelop.Ide; -using System.Linq; -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.TypeSystem; -using Mono.TextEditor; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.Semantics; -using ICSharpCode.NRefactory.CSharp.Completion; -using ICSharpCode.NRefactory.CSharp.TypeSystem; -using MonoDevelop.Ide.Gui.Content; -using MonoDevelop.Ide.TypeSystem; -using System.Threading; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using MonoDevelop.Core.Assemblies; -using MonoDevelop.Projects; -using ICSharpCode.NRefactory.TypeSystem.Implementation; -using MonoDevelop.Core.ProgressMonitoring; -using ICSharpCode.NRefactory.Completion; - -namespace MonoDevelop.Refactoring -{ - public class ResolveCommandHandler : CommandHandler - { - public static bool ResolveAt (Document doc, out ResolveResult resolveResult, out AstNode node, CancellationToken token = default (CancellationToken)) - { - if (doc == null) - throw new ArgumentNullException ("doc"); - var editor = doc.Editor; - if (editor == null || editor.MimeType != "text/x-csharp") { - node = null; - resolveResult = null; - return false; - } - if (!InternalResolveAt (doc, out resolveResult, out node)) { - var location = RefactoringService.GetCorrectResolveLocation (doc, editor.Caret.Location); - resolveResult = GetHeuristicResult (doc, location, ref node); - if (resolveResult == null) - return false; - } - var oce = node as ObjectCreateExpression; - if (oce != null) - node = oce.Type; - return true; - } - - static bool InternalResolveAt (Document doc, out ResolveResult resolveResult, out AstNode node, CancellationToken token = default (CancellationToken)) - { - var parsedDocument = doc.ParsedDocument; - resolveResult = null; - node = null; - if (parsedDocument == null) - return false; - var unit = parsedDocument.GetAst<SyntaxTree> (); - var parsedFile = parsedDocument.ParsedFile as CSharpUnresolvedFile; - if (unit == null || parsedFile == null) - return false; - try { - var location = RefactoringService.GetCorrectResolveLocation (doc, doc.Editor.Caret.Location); - resolveResult = ResolveAtLocation.Resolve (doc.Compilation, parsedFile, unit, location, out node, token); - if (resolveResult == null || node is Statement) - return false; - } catch (OperationCanceledException) { - return false; - } catch (Exception e) { - Console.WriteLine ("Got resolver exception:" + e); - return false; - } - return true; - } - - protected override void Update (CommandArrayInfo ainfo) - { - var doc = IdeApp.Workbench.ActiveDocument; - if (doc == null || doc.FileName == FilePath.Null || doc.ParsedDocument == null) - return; - - ResolveResult resolveResult; - AstNode node; - if (!ResolveAt (doc, out resolveResult, out node)) - return; - var resolveMenu = new CommandInfoSet (); - resolveMenu.Text = GettextCatalog.GetString ("Resolve"); - - var possibleNamespaces = GetPossibleNamespaces (doc, node, ref resolveResult); - - foreach (var t in possibleNamespaces.Where (tp => tp.OnlyAddReference)) { - var reference = t.Reference; - var info = resolveMenu.CommandInfos.Add ( - t.GetImportText (), - new System.Action (new AddImport (doc, resolveResult, null, reference, true, node).Run) - ); - info.Icon = MonoDevelop.Ide.Gui.Stock.AddNamespace; - - } - - - bool addUsing = !(resolveResult is AmbiguousTypeResolveResult); - if (addUsing) { - foreach (var t in possibleNamespaces.Where (tp => tp.IsAccessibleWithGlobalUsing)) { - string ns = t.Namespace; - var reference = t.Reference; - var info = resolveMenu.CommandInfos.Add ( - t.GetImportText (), - new System.Action (new AddImport (doc, resolveResult, ns, reference, true, node).Run) - ); - info.Icon = MonoDevelop.Ide.Gui.Stock.AddNamespace; - } - } - - bool resolveDirect = !(resolveResult is UnknownMemberResolveResult); - if (resolveDirect) { - if (resolveMenu.CommandInfos.Count > 0) - resolveMenu.CommandInfos.AddSeparator (); - foreach (var t in possibleNamespaces) { - string ns = t.Namespace; - var reference = t.Reference; - resolveMenu.CommandInfos.Add (t.GetInsertNamespaceText (doc.Editor.GetTextBetween (node.StartLocation, node.EndLocation)), new System.Action (new AddImport (doc, resolveResult, ns, reference, false, node).Run)); - } - } - - if (resolveMenu.CommandInfos.Count > 0) - ainfo.Insert (0, resolveMenu); - } - - static string CreateStub (Document doc, int offset) - { - if (offset <= 0) - return ""; - string text = doc.Editor.GetTextAt (0, Math.Min (doc.Editor.Length, offset)); - var stub = new StringBuilder (text); - CSharpCompletionEngine.AppendMissingClosingBrackets (stub, false); - return stub.ToString (); - } - - static ResolveResult GetHeuristicResult (Document doc, DocumentLocation location, ref AstNode node) - { - var editor = doc.Editor; - if (editor == null || editor.Caret == null) - return null; - int offset = editor.Caret.Offset; - bool wasLetter = false, wasWhitespaceAfterLetter = false; - while (offset < editor.Length) { - char ch = editor.GetCharAt (offset); - bool isLetter = char.IsLetterOrDigit (ch) || ch == '_'; - bool isWhiteSpace = char.IsWhiteSpace (ch); - bool isValidPunc = ch == '.' || ch == '<' || ch == '>'; - - if (!(wasLetter && wasWhitespaceAfterLetter) && (isLetter || isWhiteSpace || isValidPunc)) { - if (isValidPunc) { - wasWhitespaceAfterLetter = false; - wasLetter = false; - } - offset++; - } else { - offset--; - while (offset > 1) { - ch = editor.GetCharAt (offset - 1); - if (!(ch == '.' || char.IsWhiteSpace (ch))) - break; - offset--; - } - break; - } - - wasLetter |= isLetter; - if (wasLetter) - wasWhitespaceAfterLetter |= isWhiteSpace; - } - - var unit = SyntaxTree.Parse (CreateStub (doc, offset), doc.FileName); - - var parsedDocument = doc.ParsedDocument; - if (parsedDocument == null) - return null; - return ResolveAtLocation.Resolve ( - doc.Compilation, - parsedDocument.ParsedFile as CSharpUnresolvedFile, - unit, - location, - out node); - } - - public static List<PossibleNamespace> GetPossibleNamespaces (Document doc, AstNode node, ref ResolveResult resolveResult) - { - if (doc == null) - throw new ArgumentNullException ("doc"); - if (node == null) - throw new ArgumentNullException ("node"); - var location = RefactoringService.GetCorrectResolveLocation (doc, doc.Editor.Caret.Location); - - if (resolveResult == null || resolveResult.Type.FullName == "System.Void") - resolveResult = GetHeuristicResult (doc, location, ref node) ?? resolveResult; - var foundNamespaces = GetPossibleNamespaces (doc, node, resolveResult, location); - - if (!(resolveResult is AmbiguousTypeResolveResult)) { - var usedNamespaces = RefactoringOptions.GetUsedNamespaces (doc, location); - foundNamespaces = foundNamespaces.Where (n => !usedNamespaces.Contains (n.Namespace)); - } - var result = new List<PossibleNamespace> (); - foreach (var ns in foundNamespaces) { - if (result.Any (n => n.Namespace == ns.Namespace)) - continue; - result.Add (ns); - } - return result; - } - - static int GetTypeParameterCount (AstNode node) - { - if (node is ObjectCreateExpression) - node = ((ObjectCreateExpression)node).Type; - if (node is SimpleType) - return ((SimpleType)node).TypeArguments.Count; - if (node is MemberType) - return ((MemberType)node).TypeArguments.Count; - if (node is IdentifierExpression) - return ((IdentifierExpression)node).TypeArguments.Count; - return 0; - } - - public class PossibleNamespace - { - public string Namespace { get; private set; } - public bool IsAccessibleWithGlobalUsing { get; private set; } - public bool OnlyAddReference { get { return !IsAccessibleWithGlobalUsing && Reference != null; } } - public MonoDevelop.Projects.ProjectReference Reference { get; private set; } - - public PossibleNamespace (string @namespace, bool isAccessibleWithGlobalUsing, MonoDevelop.Projects.ProjectReference reference = null) - { - this.Namespace = @namespace; - this.IsAccessibleWithGlobalUsing = isAccessibleWithGlobalUsing; - this.Reference = reference; - } - - string GetLibraryName () - { - var txt = Reference.Reference; - int idx = txt.IndexOf (','); - if (idx >= 0) - return txt.Substring (0, idx); - return txt; - } - - public string GetImportText () - { - if (OnlyAddReference) - return GettextCatalog.GetString ( - "Reference '{0}'", - GetLibraryName ().Replace ("_", "__")); - if (Reference != null) - return GettextCatalog.GetString ( - "Reference '{0}' and use '{1}'", - GetLibraryName (), - string.Format ("using {0};", Namespace.Replace ("_", "__"))); - - return string.Format ("using {0};", Namespace.Replace ("_", "__")); - } - - public string GetInsertNamespaceText (string member) - { - if (Reference != null) - return GettextCatalog.GetString ( - "Reference '{0}' and use '{1}'", - GetLibraryName ().Replace ("_", "__"), - (Namespace + "." + member).Replace ("_", "__") - ); - return (Namespace + "." + member).Replace ("_", "__"); - } - } - - internal static bool CanBeReferenced (Project project, SystemAssembly systemAssembly) - { - var netProject = project as DotNetProject; - if (netProject == null) - return false; - var result = netProject.TargetRuntime.AssemblyContext.GetAssemblyNameForVersion(systemAssembly.FullName, netProject.TargetFramework); - return !string.IsNullOrEmpty (result); - } - - static bool CanReference (Document doc, MonoDevelop.Projects.ProjectReference projectReference) - { - var project = doc.Project as DotNetProject; - if (project == null || projectReference == null || project.ParentSolution == null) - return true; - switch (projectReference.ReferenceType) { - case ReferenceType.Project: - var referenceProject = projectReference.ResolveProject (project.ParentSolution) as DotNetProject; - if (referenceProject == null) - return true; - string reason; - return project.CanReferenceProject (referenceProject, out reason); - } - return true; - - } - - static IEnumerable<PossibleNamespace> GetPossibleNamespaces (Document doc, AstNode node, ResolveResult resolveResult, DocumentLocation location) - { - var unit = doc.ParsedDocument.GetAst<SyntaxTree> (); - if (unit == null) - yield break; - var project = doc.Project; - if (project == null) - yield break; - int tc = GetTypeParameterCount (node); - var attribute = unit.GetNodeAt<ICSharpCode.NRefactory.CSharp.Attribute> (location); - bool isInsideAttributeType = attribute != null && attribute.Type.Contains (location); - - var compilations = new List<Tuple<ICompilation, MonoDevelop.Projects.ProjectReference>> (); - compilations.Add (Tuple.Create (doc.Compilation, (MonoDevelop.Projects.ProjectReference)null)); - var referencedItems = IdeApp.Workspace != null ? project.GetReferencedItems (IdeApp.Workspace.ActiveConfiguration).ToList () : (IEnumerable<SolutionFolderItem>) new SolutionFolderItem[0]; - var solution = project != null ? project.ParentSolution : null; - if (solution != null) { - foreach (var curProject in solution.GetAllProjects ()) { - if (curProject == project || referencedItems.Contains (curProject)) - continue; - - var otherRefes = IdeApp.Workspace != null ? curProject.GetReferencedItems (IdeApp.Workspace.ActiveConfiguration).ToList () : (IEnumerable<SolutionFolderItem>) new SolutionFolderItem[0]; - if (otherRefes.Contains (project)) - continue; - - var comp = TypeSystemService.GetCompilation (curProject); - if (comp == null) - continue; - compilations.Add (Tuple.Create (comp, new MonoDevelop.Projects.ProjectReference (curProject))); - } - } - - var netProject = project as DotNetProject; - if (netProject == null) - yield break; - FrameworkLookup frameworkLookup; - if (!TypeSystemService.TryGetFrameworkLookup (netProject, out frameworkLookup)) - frameworkLookup = null; - if (frameworkLookup != null && resolveResult is UnknownMemberResolveResult) { - var umResult = (UnknownMemberResolveResult)resolveResult; - try { - foreach (var r in frameworkLookup.GetExtensionMethodLookups (umResult)) { - var systemAssembly = netProject.AssemblyContext.GetAssemblyFromFullName (r.FullName, r.Package, netProject.TargetFramework); - if (systemAssembly == null) - continue; - if (CanBeReferenced (doc.Project, systemAssembly)) - compilations.Add (Tuple.Create (TypeSystemService.GetCompilation (systemAssembly, doc.Compilation), new MonoDevelop.Projects.ProjectReference (systemAssembly))); - } - } catch (Exception e) { - if (!TypeSystemService.RecreateFrameworkLookup (netProject)) - LoggingService.LogError (string.Format ("Error while looking up extension method {0}", umResult.MemberName), e); - } - } - bool foundIdentifier = false; - var lookup = new MemberLookup (null, doc.Compilation.MainAssembly); - foreach (var comp in compilations) { - var compilation = comp.Item1; - var requiredReference = comp.Item2; - if (resolveResult is AmbiguousTypeResolveResult) { - if (compilation != doc.Compilation) - continue; - var aResult = resolveResult as AmbiguousTypeResolveResult; - var file = doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile; - var scope = file.GetUsingScope (location).Resolve (compilation); - while (scope != null) { - foreach (var u in scope.Usings) { - foreach (var typeDefinition in u.Types) { - if (typeDefinition.Name == aResult.Type.Name && - typeDefinition.TypeParameterCount == tc && - lookup.IsAccessible (typeDefinition, false)) { - if (CanReference(doc, requiredReference)) - yield return new PossibleNamespace (typeDefinition.Namespace, true, requiredReference); - } - } - } - scope = scope.Parent; - } - } - var allTypes = compilation == doc.Compilation ? compilation.GetAllTypeDefinitions () : compilation.MainAssembly.GetAllTypeDefinitions (); - if (resolveResult is UnknownIdentifierResolveResult) { - var uiResult = resolveResult as UnknownIdentifierResolveResult; - string possibleAttributeName = isInsideAttributeType ? uiResult.Identifier + "Attribute" : uiResult.Identifier; - foreach (var typeDefinition in allTypes) { - if ((typeDefinition.Name == possibleAttributeName || typeDefinition.Name == uiResult.Identifier) && typeDefinition.TypeParameterCount == tc && - lookup.IsAccessible (typeDefinition, false)) { - if (CanReference (doc, requiredReference)) { - if (typeDefinition.DeclaringTypeDefinition != null) { - var builder = new TypeSystemAstBuilder (new CSharpResolver (doc.Compilation)); - foundIdentifier = true; - yield return new PossibleNamespace (builder.ConvertType (typeDefinition.DeclaringTypeDefinition).ToString (), false, requiredReference); - } else { - foundIdentifier = true; - yield return new PossibleNamespace (typeDefinition.Namespace, true, requiredReference); - } - } - } - } - } - - if (resolveResult is UnknownMemberResolveResult) { - var umResult = (UnknownMemberResolveResult)resolveResult; - string possibleAttributeName = isInsideAttributeType ? umResult.MemberName + "Attribute" : umResult.MemberName; - foreach (var typeDefinition in allTypes.Where (t => t.HasExtensionMethods)) { - if (!lookup.IsAccessible (typeDefinition, false)) - continue; - foreach (var method in typeDefinition.Methods.Where (m => m.IsExtensionMethod && (m.Name == possibleAttributeName || m.Name == umResult.MemberName))) { - if (!lookup.IsAccessible (method, false)) - continue; - IType[] inferredTypes; - if (CSharpResolver.IsEligibleExtensionMethod ( - compilation.Import (umResult.TargetType), - method, - true, - out inferredTypes - )) { - if (CanReference(doc, requiredReference)) - yield return new PossibleNamespace (typeDefinition.Namespace, true, requiredReference); - goto skipType; - } - } - skipType: - ; - } - } - - if (resolveResult is ErrorResolveResult) { - var identifier = unit != null ? unit.GetNodeAt<Identifier> (location) : null; - if (identifier != null) { - var uiResult = resolveResult as UnknownIdentifierResolveResult; - if (uiResult != null) { - string possibleAttributeName = isInsideAttributeType ? uiResult.Identifier + "Attribute" : uiResult.Identifier; - foreach (var typeDefinition in allTypes) { - if ((identifier.Name == possibleAttributeName || identifier.Name == uiResult.Identifier) && - typeDefinition.TypeParameterCount == tc && - lookup.IsAccessible (typeDefinition, false)) - if (CanReference(doc, requiredReference)) - yield return new PossibleNamespace (typeDefinition.Namespace, true, requiredReference); - } - } - } - } - } - - // Try to search framework types - if (!foundIdentifier && frameworkLookup != null && resolveResult is UnknownIdentifierResolveResult && node is AstType) { - var uiResult = resolveResult as UnknownIdentifierResolveResult; - if (uiResult != null) { - var lookups = new List<Tuple<FrameworkLookup.AssemblyLookup, SystemAssembly>> (); - try { - foreach (var r in frameworkLookup.GetLookups (uiResult, tc, isInsideAttributeType)) { - var systemAssembly = netProject.AssemblyContext.GetAssemblyFromFullName (r.FullName, r.Package, netProject.TargetFramework); - if (systemAssembly == null) - continue; - if (CanBeReferenced (doc.Project, systemAssembly)) - lookups.Add (Tuple.Create (r, systemAssembly)); - } - } catch (Exception e) { - if (!TypeSystemService.RecreateFrameworkLookup (netProject)) - LoggingService.LogError (string.Format ("Error while looking up identifier {0}", uiResult.Identifier), e); - } - foreach(var kv in lookups) - if (CanReference(doc, new MonoDevelop.Projects.ProjectReference (kv.Item2))) - yield return new PossibleNamespace (kv.Item1.Namespace, true, new MonoDevelop.Projects.ProjectReference (kv.Item2)); - - } - } - if (!foundIdentifier && frameworkLookup != null && resolveResult is UnknownMemberResolveResult) { - var uiResult = resolveResult as UnknownMemberResolveResult; - if (uiResult != null) { - var lookups = new List<Tuple<FrameworkLookup.AssemblyLookup, SystemAssembly>> (); - try { - foreach (var r in frameworkLookup.GetLookups (uiResult, node.ToString (), tc, isInsideAttributeType)) { - var systemAssembly = netProject.AssemblyContext.GetAssemblyFromFullName (r.FullName, r.Package, netProject.TargetFramework); - if (systemAssembly == null) - continue; - if (CanBeReferenced (doc.Project, systemAssembly)) - lookups.Add (Tuple.Create (r, systemAssembly)); - } - } catch (Exception e) { - if (!TypeSystemService.RecreateFrameworkLookup (netProject)) - LoggingService.LogError (string.Format ("Error while looking up member resolve result {0}", node), e); - } - foreach(var kv in lookups) - if (CanReference(doc, new MonoDevelop.Projects.ProjectReference (kv.Item2))) - yield return new PossibleNamespace (kv.Item1.Namespace, true, new MonoDevelop.Projects.ProjectReference (kv.Item2)); - } - } - - } - - internal class AddImport - { - readonly Document doc; - readonly ResolveResult resolveResult; - readonly string ns; - readonly bool addUsing; - readonly AstNode node; - readonly MonoDevelop.Projects.ProjectReference reference; - - public AddImport (Document doc, ResolveResult resolveResult, string ns, MonoDevelop.Projects.ProjectReference reference, bool addUsing, AstNode node) - { - this.doc = doc; - this.resolveResult = resolveResult; - this.ns = ns; - this.reference = reference; - this.addUsing = addUsing; - this.node = node; - } - - public void Run () - { - var loc = doc.Editor.Caret.Location; - - if (reference != null) { - var project = doc.Project; - project.Items.Add (reference); - IdeApp.ProjectOperations.SaveAsync (project); - } - - if (string.IsNullOrEmpty (ns)) - return; - - if (!addUsing) { -// var unit = doc.ParsedDocument.GetAst<SyntaxTree> (); - int offset = doc.Editor.LocationToOffset (node.StartLocation); - doc.Editor.Insert (offset, ns + "."); - doc.Editor.Document.CommitLineUpdate (loc.Line); - return; - } - - var generator = doc.CreateCodeGenerator (); - - if (resolveResult is NamespaceResolveResult) { - generator.AddLocalNamespaceImport (doc, ns, loc); - } else { - generator.AddGlobalNamespaceImport (doc, ns); - } - } - } - - protected override void Run (object data) - { - var del = (System.Action)data; - if (del != null) - del (); - } - } -} - diff --git a/main/src/addins/MonoDevelop.Refactoring/gtk-gui/gui.stetic b/main/src/addins/MonoDevelop.Refactoring/gtk-gui/gui.stetic index 11b6e6c4d6..9f49f22dde 100644 --- a/main/src/addins/MonoDevelop.Refactoring/gtk-gui/gui.stetic +++ b/main/src/addins/MonoDevelop.Refactoring/gtk-gui/gui.stetic @@ -6,9 +6,8 @@ </configuration> <import> <widget-library name="../../../../build/bin/MonoDevelop.Ide.dll" /> - <widget-library name="../../../../build/bin/Mono.TextEditor.dll" /> <widget-library name="../../../../build/AddIns/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport.dll" /> - <widget-library name="../../../../build/AddIns/DisplayBindings/SourceEditor/MonoDevelop.SourceEditor2.dll" /> + <widget-library name="../../../../build/AddIns/DisplayBindings/SourceEditor/MonoDevelop.SourceEditor.dll" /> <widget-library name="../../../../build/AddIns/MonoDevelop.Refactoring/MonoDevelop.Refactoring.dll" internal="true" /> </import> <widget class="Gtk.Dialog" id="MonoDevelop.Refactoring.RefactoringPreviewDialog" design-size="400 300"> diff --git a/main/src/addins/MonoDevelop.Refactoring/packages.config b/main/src/addins/MonoDevelop.Refactoring/packages.config new file mode 100644 index 0000000000..796aed48f4 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/packages.config @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Microsoft.CodeAnalysis.Common" version="1.0.0-rc1" targetFramework="net45" />
+ <package id="Microsoft.CodeAnalysis.CSharp" version="1.0.0-rc1" targetFramework="net45" />
+ <package id="Microsoft.CodeAnalysis.CSharp.Workspaces" version="1.0.0-rc1" targetFramework="net45" />
+ <package id="Microsoft.CodeAnalysis.Workspaces.Common" version="1.0.0-rc1" targetFramework="net45" />
+ <package id="Microsoft.Composition" version="1.0.27" targetFramework="net45" />
+ <package id="System.Collections.Immutable" version="1.1.33-beta" targetFramework="net45" />
+ <package id="System.Reflection.Metadata" version="1.0.18-beta" targetFramework="net45" />
+</packages>
\ No newline at end of file |