Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@1389 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
29 changed files with 565 additions and 175 deletions
@ -0,0 +1,129 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using ICSharpCode.Core; |
||||||
|
using ICSharpCode.NRefactory.Parser.AST; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
using NR = ICSharpCode.NRefactory.Parser; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Refactoring |
||||||
|
{ |
||||||
|
public class NRefactoryRefactoringProvider : RefactoringProvider |
||||||
|
{ |
||||||
|
public static readonly NRefactoryRefactoringProvider NRefactoryProviderInstance = new NRefactoryRefactoringProvider(); |
||||||
|
|
||||||
|
protected class PossibleTypeReference |
||||||
|
{ |
||||||
|
internal string Name; |
||||||
|
internal bool Global; |
||||||
|
internal int TypeParameterCount; |
||||||
|
|
||||||
|
public PossibleTypeReference(string name) |
||||||
|
{ |
||||||
|
this.Name = name; |
||||||
|
} |
||||||
|
|
||||||
|
public PossibleTypeReference(TypeReference tr) |
||||||
|
{ |
||||||
|
this.Name = tr.SystemType; |
||||||
|
this.Global = tr.IsGlobal; |
||||||
|
this.TypeParameterCount = tr.GenericTypes.Count; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetHashCode() |
||||||
|
{ |
||||||
|
return Name.GetHashCode() ^ Global.GetHashCode() ^ TypeParameterCount.GetHashCode(); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool Equals(object obj) |
||||||
|
{ |
||||||
|
if (!(obj is PossibleTypeReference)) return false; |
||||||
|
if (this == obj) return true; |
||||||
|
PossibleTypeReference myPossibleTypeReference = (PossibleTypeReference)obj; |
||||||
|
return this.Name == myPossibleTypeReference.Name && this.Global == myPossibleTypeReference.Global && this.TypeParameterCount == myPossibleTypeReference.TypeParameterCount; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private class FindPossibleTypeReferencesVisitor : NR.AbstractAstVisitor |
||||||
|
{ |
||||||
|
internal Dictionary<PossibleTypeReference, object> list = new Dictionary<PossibleTypeReference, object>(); |
||||||
|
|
||||||
|
public override object Visit(IdentifierExpression identifierExpression, object data) |
||||||
|
{ |
||||||
|
list[new PossibleTypeReference(identifierExpression.Identifier)] = data; |
||||||
|
return base.Visit(identifierExpression, data); |
||||||
|
} |
||||||
|
|
||||||
|
public override object Visit(TypeReference typeReference, object data) |
||||||
|
{ |
||||||
|
list[new PossibleTypeReference(typeReference)] = data; |
||||||
|
return base.Visit(typeReference, data); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected Dictionary<PossibleTypeReference, object> FindPossibleTypeReferences(string extension, string fileContent) |
||||||
|
{ |
||||||
|
NR.IParser parser; |
||||||
|
if (extension.Equals(".cs", StringComparison.InvariantCultureIgnoreCase)) |
||||||
|
parser = NR.ParserFactory.CreateParser(NR.SupportedLanguage.CSharp, new StringReader(fileContent)); |
||||||
|
else if (extension.Equals(".vb", StringComparison.InvariantCultureIgnoreCase)) |
||||||
|
parser = NR.ParserFactory.CreateParser(NR.SupportedLanguage.VBNet, new StringReader(fileContent)); |
||||||
|
else |
||||||
|
return null; |
||||||
|
parser.Parse(); |
||||||
|
if (parser.Errors.count > 0) { |
||||||
|
MessageService.ShowMessage("The operation cannot be performed because your sourcecode contains errors:\n" + parser.Errors.ErrorOutput); |
||||||
|
return null; |
||||||
|
} else { |
||||||
|
FindPossibleTypeReferencesVisitor visitor = new FindPossibleTypeReferencesVisitor(); |
||||||
|
parser.CompilationUnit.AcceptVisitor(visitor, null); |
||||||
|
return visitor.list; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override bool SupportsFindUnusedUsingDeclarations { |
||||||
|
get { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public override IList<IUsing> FindUnusedUsingDeclarations(string fileName, string fileContent, ICompilationUnit cu) |
||||||
|
{ |
||||||
|
IClass @class = cu.Classes.Count == 0 ? null : cu.Classes[0]; |
||||||
|
|
||||||
|
Dictionary<PossibleTypeReference, object> references = FindPossibleTypeReferences(Path.GetExtension(fileName), fileContent); |
||||||
|
if (references == null) return new IUsing[0]; |
||||||
|
|
||||||
|
Dictionary<IUsing, object> dict = new Dictionary<IUsing, object>(); |
||||||
|
foreach (PossibleTypeReference tr in references.Keys) { |
||||||
|
SearchTypeRequest request = new SearchTypeRequest(tr.Name, tr.TypeParameterCount, @class, cu, 1, 1); |
||||||
|
SearchTypeResult response = cu.ProjectContent.SearchType(request); |
||||||
|
if (response.UsedUsing != null) { |
||||||
|
dict[response.UsedUsing] = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
List<IUsing> list = new List<IUsing>(); |
||||||
|
foreach (IUsing import in cu.Usings) { |
||||||
|
if (!dict.ContainsKey(import)) { |
||||||
|
if (import.HasAliases) { |
||||||
|
foreach (string key in import.Aliases.Keys) { |
||||||
|
if (references.ContainsKey(new PossibleTypeReference(key))) |
||||||
|
goto checkNextImport; |
||||||
|
} |
||||||
|
} |
||||||
|
list.Add(import); // this using is unused
|
||||||
|
} |
||||||
|
checkNextImport:; |
||||||
|
} |
||||||
|
return list; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,16 +0,0 @@ |
|||||||
// <file>
|
|
||||||
// <copyright see="prj:///doc/copyright.txt"/>
|
|
||||||
// <license see="prj:///doc/license.txt"/>
|
|
||||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
|
||||||
// <version>$Revision$</version>
|
|
||||||
// </file>
|
|
||||||
|
|
||||||
using System; |
|
||||||
|
|
||||||
namespace ICSharpCode.SharpDevelop.Refactoring |
|
||||||
{ |
|
||||||
public static class NamespaceRefactoring |
|
||||||
{ |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,70 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using ICSharpCode.Core; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
using ICSharpCode.TextEditor.Document; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Refactoring |
||||||
|
{ |
||||||
|
public static class NamespaceRefactoringService |
||||||
|
{ |
||||||
|
static int CompareUsings(IUsing a, IUsing b) |
||||||
|
{ |
||||||
|
if (a.HasAliases != b.HasAliases) |
||||||
|
return a.HasAliases ? 1 : -1; |
||||||
|
if (a.Usings.Count != 0 && b.Usings.Count != 0) { |
||||||
|
string u1 = a.Usings[0]; |
||||||
|
string u2 = b.Usings[0]; |
||||||
|
if (u1.StartsWith("System.") || u1 == "System") { |
||||||
|
if (!(u2.StartsWith("System.") || u2 == "System")) |
||||||
|
return -1; |
||||||
|
} else { |
||||||
|
if (u2.StartsWith("System.") || u2 == "System") |
||||||
|
return 1; |
||||||
|
} |
||||||
|
return a.Usings[0].CompareTo(b.Usings[0]); |
||||||
|
} |
||||||
|
if (a.Aliases.Count != 0 && b.Aliases.Count != 0) { |
||||||
|
return a.Aliases.Keys[0].CompareTo(b.Aliases.Keys[0]); |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public static void ManageUsings(string fileName, IDocument document, bool sort, bool removedUnused) |
||||||
|
{ |
||||||
|
ParseInformation info = ParserService.ParseFile(fileName, document.TextContent); |
||||||
|
if (info == null) return; |
||||||
|
ICompilationUnit cu = info.MostRecentCompilationUnit; |
||||||
|
|
||||||
|
List<IUsing> newUsings = new List<IUsing>(cu.Usings); |
||||||
|
if (sort) { |
||||||
|
newUsings.Sort(CompareUsings); |
||||||
|
} |
||||||
|
|
||||||
|
if (removedUnused) { |
||||||
|
IList<IUsing> decl = cu.ProjectContent.Language.RefactoringProvider.FindUnusedUsingDeclarations(fileName, document.TextContent, cu); |
||||||
|
if (decl != null && decl.Count > 0) { |
||||||
|
foreach (IUsing u in decl) { |
||||||
|
string ns = null; |
||||||
|
for (int i = 0; i < u.Usings.Count; i++) { |
||||||
|
ns = u.Usings[i]; |
||||||
|
if (ns == "System") break; |
||||||
|
} |
||||||
|
if (ns != "System") { // never remove "using System;"
|
||||||
|
newUsings.Remove(u); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
cu.ProjectContent.Language.CodeGenerator.ReplaceUsings(document, cu.Usings, newUsings); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Reflection; |
||||||
|
using ICSharpCode.Core; |
||||||
|
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
using ICSharpCode.SharpDevelop.Gui; |
||||||
|
using ICSharpCode.TextEditor; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Refactoring |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Tests if the refactoring provider for the current document
|
||||||
|
/// supports the specified option.
|
||||||
|
/// </summary>
|
||||||
|
/// <attribute name="supports">
|
||||||
|
/// Same of the action that should be supported.
|
||||||
|
/// "*" to test if refactoring is supported at all.
|
||||||
|
/// </attribute>
|
||||||
|
/// <example title="Test if refactoring is supported">
|
||||||
|
/// <Condition name="RefactoringProviderSupports" supports="*">
|
||||||
|
/// </example>
|
||||||
|
/// <example title="Test if managing imports is supported">
|
||||||
|
/// <Condition name="RefactoringProviderSupports" supports="FindUnusedUsingDeclarations">
|
||||||
|
/// </example>
|
||||||
|
public class RefactoringProviderSupportsConditionEvaluator : IConditionEvaluator |
||||||
|
{ |
||||||
|
public bool IsValid(object caller, Condition condition) |
||||||
|
{ |
||||||
|
if (WorkbenchSingleton.Workbench == null || WorkbenchSingleton.Workbench.ActiveWorkbenchWindow == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
ITextEditorControlProvider provider = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent as ITextEditorControlProvider; |
||||||
|
if (provider == null) return false; |
||||||
|
LanguageProperties language = ParserService.CurrentProjectContent.Language; |
||||||
|
if (language == null) return false; |
||||||
|
|
||||||
|
string supports = condition.Properties["supports"]; |
||||||
|
if (supports == "*") return true; |
||||||
|
RefactoringProvider rp = language.RefactoringProvider; |
||||||
|
Type t = rp.GetType(); |
||||||
|
try { |
||||||
|
return (bool)t.InvokeMember("Supports" + supports, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty, null, rp, null); |
||||||
|
} catch (Exception ex) { |
||||||
|
LoggingService.Warn(ex.ToString()); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public abstract class AbstractRefactoringCommand : AbstractMenuCommand |
||||||
|
{ |
||||||
|
public override void Run() |
||||||
|
{ |
||||||
|
if (ParserService.LoadSolutionProjectsThreadRunning) { |
||||||
|
return; |
||||||
|
} |
||||||
|
if (WorkbenchSingleton.Workbench == null || WorkbenchSingleton.Workbench.ActiveWorkbenchWindow == null) { |
||||||
|
return; |
||||||
|
} |
||||||
|
ITextEditorControlProvider provider = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent as ITextEditorControlProvider; |
||||||
|
if (provider == null) return; |
||||||
|
LanguageProperties language = ParserService.CurrentProjectContent.Language; |
||||||
|
if (language == null) return; |
||||||
|
|
||||||
|
RefactoringProvider rp = language.RefactoringProvider; |
||||||
|
Run(provider.TextEditorControl, rp); |
||||||
|
provider.TextEditorControl.Refresh(); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract void Run(TextEditorControl textEditor, RefactoringProvider provider); |
||||||
|
} |
||||||
|
|
||||||
|
public class RemoveUnusedUsingsCommand : AbstractRefactoringCommand |
||||||
|
{ |
||||||
|
protected override void Run(TextEditorControl textEditor, RefactoringProvider provider) |
||||||
|
{ |
||||||
|
NamespaceRefactoringService.ManageUsings(textEditor.FileName, textEditor.Document, true, true); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
// <file>
|
||||||
|
// <copyright see="prj:///doc/copyright.txt"/>
|
||||||
|
// <license see="prj:///doc/license.txt"/>
|
||||||
|
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||||
|
// <version>$Revision$</version>
|
||||||
|
// </file>
|
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using ICSharpCode.SharpDevelop.Dom; |
||||||
|
|
||||||
|
namespace ICSharpCode.SharpDevelop.Refactoring |
||||||
|
{ |
||||||
|
public class RefactoringProvider |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// A RefactoringProvider instance that supports no refactorings.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly RefactoringProvider DummyProvider = new RefactoringProvider(); |
||||||
|
|
||||||
|
protected RefactoringProvider() {} |
||||||
|
|
||||||
|
public virtual bool SupportsFindUnusedUsingDeclarations { |
||||||
|
get { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public virtual IList<IUsing> FindUnusedUsingDeclarations(string fileName, string fileContent, ICompilationUnit compilationUnit) |
||||||
|
{ |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue