diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs index e826a9a9e4..237a722d8a 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -1261,7 +1261,8 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } } var isAsWrapper = new CompletionDataWrapper (this); - AddTypesAndNamespaces(isAsWrapper, GetState(), null, t => isAsType == null || t.GetDefinition().IsDerivedFrom(isAsType.GetDefinition()), m => false); + var def = isAsType.GetDefinition(); + AddTypesAndNamespaces(isAsWrapper, GetState(), null, t => t.GetDefinition() != null && def != null && (isAsType == null || t.GetDefinition().IsDerivedFrom(def)), m => false); return isAsWrapper.Result; // { // CompletionDataList completionList = new ProjectDomCompletionDataList (); diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantUsingInspector.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantUsingInspector.cs index 4800b07b30..c60a0f099b 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantUsingInspector.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/Inspector/RedundantUsingInspector.cs @@ -29,6 +29,8 @@ using ICSharpCode.NRefactory.PatternMatching; using System.Collections.Generic; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.CSharp.Resolver; +using System.Linq; namespace ICSharpCode.NRefactory.CSharp.Refactoring { @@ -37,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring /// public class RedundantUsingInspector : IInspector { - string title = "Remove redundant using"; + string title = "Remove redundant usings"; public string Title { get { @@ -52,26 +54,77 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring { var visitor = new GatherVisitor (context, this); context.RootNode.AcceptVisitor (visitor); + visitor.Collect (); return visitor.FoundIssues; } class GatherVisitor : GatherVisitorBase { readonly RedundantUsingInspector inspector; + Dictionary usingDeclarations = new Dictionary (); + + Stack> usingStack = new Stack> (); public GatherVisitor (BaseRefactoringContext ctx, RedundantUsingInspector inspector) : base (ctx) { this.inspector = inspector; + usingStack.Push (new List ()); + } + + public void Collect () + { + foreach (var u in usingDeclarations.Where (u => !u.Value)) { + var decl = u.Key; + AddIssue (decl, inspector.Title, delegate { + using (var script = ctx.StartScript ()) { + foreach (var u2 in usingDeclarations.Where (a => !a.Value)) { + script.Remove (u2.Key); + } + } + } + ); + } } public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration) { base.VisitUsingDeclaration(usingDeclaration); - // TODO - // return cSharpResolver.usedScopes - // .OfType () - // .Any (u => u.ResolveNamespace (ctx).NamespaceName == ns) || additionalNamespaces.Contains (ns); + usingDeclarations [usingDeclaration] = false; + usingStack.Peek().Add(usingDeclaration); } + + public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) + { + usingStack.Push(new List (usingStack.Peek())); + base.VisitNamespaceDeclaration(namespaceDeclaration); + usingStack.Pop(); + } + + void UseNamespace(string ns) + { + foreach (var u in usingStack.Peek ()) { + if (u.Namespace == ns) { + usingDeclarations [u] = true; + } + } + } + + public override void VisitIdentifierExpression(IdentifierExpression identifierExpression) + { + base.VisitIdentifierExpression(identifierExpression); + UseNamespace(ctx.Resolve(identifierExpression).Type.Namespace); + } + + public override void VisitInvocationExpression (InvocationExpression invocationExpression) + { + base.VisitInvocationExpression (invocationExpression); + var mg = ctx.Resolve (invocationExpression) as CSharpInvocationResolveResult; + if (mg == null || !mg.IsExtensionMethodInvocation) { + return; + } + UseNamespace (mg.Member.DeclaringType.Namespace); + } + } } }