From 0f5a586493e343a996095e0826192dfc69653f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kon=C3=AD=C4=8Dek?= Date: Sun, 22 Aug 2010 17:18:51 +0000 Subject: [PATCH] Moved "Resolve extension method" to context actions. Expand selection (Ctrl+W) does not include { and } when selecting BlockStatement. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6439 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../AvalonEdit.AddIn/Src/CodeEditorView.cs | 2 + .../Project/Src/ContextActions/AddUsing.cs | 55 +++++++++++++------ .../Src/Visitors/SetRegionInclusionVisitor.cs | 14 ++++- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs index f6d4b3685c..6197c9a8b6 100755 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs @@ -376,6 +376,7 @@ namespace ICSharpCode.AvalonEdit.AddIn } #endregion + #region Expand selection protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); @@ -414,6 +415,7 @@ namespace ICSharpCode.AvalonEdit.AddIn this.Select(startOffset, endOffset - startOffset); } } + #endregion public void JumpTo(int line, int column) { diff --git a/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs index 777df1b4fe..989d85164f 100644 --- a/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs +++ b/src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs @@ -22,36 +22,63 @@ namespace SharpRefactoring.ContextActions { public override IEnumerable GetAvailableActions(EditorContext context) { - var currentLineAST = context.CurrentLineAST; - if (currentLineAST == null) - yield break; - var symbol = context.CurrentSymbol; - foreach (var contextAction in GetAddUsingContextActions(symbol, context.Editor, context.CurrentExpression.Context)) { + foreach (var contextAction in GetAddUsingContextActions(context.CurrentSymbol, context.Editor, context.CurrentExpression.Context)) { yield return contextAction; } } IEnumerable GetAddUsingContextActions(ResolveResult symbol, ITextEditor editor, ExpressionContext exprContext) { + // class foreach (var addUsingAction in RefactoringService.GetAddUsingActions(symbol,editor)) { yield return addUsingAction; } + // extension method + if (exprContext != ExpressionContext.Attribute) { + foreach (var addUsingAction in GetAddUsingExtensionMethodActions(symbol, editor)) { + yield return addUsingAction; + } + } + // attribute if (exprContext == ExpressionContext.Attribute) { foreach (var addUsingAction in GetAddUsingAttributeActions(symbol, editor)) { yield return addUsingAction; } } - foreach (var addUsingAction in GetAddUsingExtensionMethodActions(symbol, editor)) { - yield return addUsingAction; - } } + #region Extension method IEnumerable GetAddUsingExtensionMethodActions(ResolveResult symbol, ITextEditor editor) { - yield break; + if (!(symbol is UnknownMethodResolveResult)) + yield break; + + UnknownMethodResolveResult rr = symbol as UnknownMethodResolveResult; + List results = new List(); + IProjectContent pc = rr.CallingClass.ProjectContent; + + SearchAllExtensionMethodsWithName(results, pc, rr.CallName); + foreach (IProjectContent content in pc.ReferencedContents) + SearchAllExtensionMethodsWithName(results, content, rr.CallName); + if (!results.Any()) + yield break; + + foreach (IClass c in results) { + yield return new RefactoringService.AddUsingAction(rr.CallingClass.CompilationUnit, editor, c.Namespace); + } + } + + void SearchAllExtensionMethodsWithName(List searchResults, IProjectContent pc, string name) + { + foreach (IClass c in pc.Classes) { + if (c.HasExtensionMethods && !searchResults.Any(cl => cl.Namespace == c.Namespace) && + c.Methods.Any(m => m.IsExtensionMethod && m.Name == name)) + searchResults.Add(c); + } } + #endregion - #region GetAddUsingAttributeActions + #region Attribute IEnumerable GetAddUsingAttributeActions(ResolveResult symbol, ITextEditor editor) { if (!(symbol is UnknownIdentifierResolveResult || symbol is UnknownMethodResolveResult)) @@ -76,13 +103,7 @@ namespace SharpRefactoring.ContextActions } foreach (IClass c in results) { - string newNamespace = c.Namespace; - yield return new DelegateAction {Title = "using " + newNamespace, - ExecuteAction = delegate { - NamespaceRefactoringService.AddUsingDeclaration(unit, editor.Document, newNamespace, true); - ParserService.BeginParse(editor.FileName, editor.Document); - } - }; + yield return new RefactoringService.AddUsingAction(unit, editor, c.Namespace); } } diff --git a/src/Libraries/NRefactory/Project/Src/Visitors/SetRegionInclusionVisitor.cs b/src/Libraries/NRefactory/Project/Src/Visitors/SetRegionInclusionVisitor.cs index 9721264467..359699f2c1 100644 --- a/src/Libraries/NRefactory/Project/Src/Visitors/SetRegionInclusionVisitor.cs +++ b/src/Libraries/NRefactory/Project/Src/Visitors/SetRegionInclusionVisitor.cs @@ -6,13 +6,14 @@ // using System; using System.Collections.Generic; +using System.Linq; using ICSharpCode.NRefactory.Ast; namespace ICSharpCode.NRefactory.Visitors { /// /// Sets StartLocation and EndLocation (region) of every node to union of regions of its children. - /// Parsers don't do this by default, + /// Parsers don't do this by default: /// e.g. "a.Foo()" is InvocationExpression, its region includes only the "()" and it has a child MemberReferenceExpression, with region ".Foo". /// public class SetRegionInclusionVisitor : NodeTrackingAstVisitor @@ -35,7 +36,7 @@ namespace ICSharpCode.NRefactory.Visitors if (node is PropertyDeclaration) { // PropertyDeclaration has correctly set BodyStart and BodyEnd by the parser, - // but it has no subnode "body", just 2 children GetRegion and SetRegion which don't cover + // but it has no subnode "body", just 2 children GetRegion and SetRegion which don't span // the whole (BodyStart, BodyEnd) region => We have to handle PropertyDeclaration as a special case. node.EndLocation = ((PropertyDeclaration)node).BodyEnd; } @@ -61,6 +62,15 @@ namespace ICSharpCode.NRefactory.Visitors if (node.EndLocation > parent.EndLocation) parent.EndLocation = node.EndLocation; } + + // Block statement as a special case - we want it without the '{' and '}' + if (node is BlockStatement) { + var firstSatement = node.Children.FirstOrDefault(); + if (firstSatement != null) { + node.StartLocation = firstSatement.StartLocation; + node.EndLocation = node.Children.Last().EndLocation; + } + } } } }