diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index cce4ae8091..01b3f8a229 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -664,6 +664,7 @@ + @@ -682,6 +683,7 @@ {35cef10f-2d4c-45f2-9dd1-161e0fec583c} ICSharpCode.Core + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Commands/ClassMemberMenuBuilder.cs b/src/Main/Base/Project/Src/Commands/ClassMemberMenuBuilder.cs index f47eed9606..e90572ae2f 100644 --- a/src/Main/Base/Project/Src/Commands/ClassMemberMenuBuilder.cs +++ b/src/Main/Base/Project/Src/Commands/ClassMemberMenuBuilder.cs @@ -13,8 +13,11 @@ using System.Windows.Forms; using ICSharpCode.Core; using ICSharpCode.TextEditor; using ICSharpCode.TextEditor.Document; +using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor; using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Bookmarks; +using ICSharpCode.SharpDevelop.Gui; +using SearchAndReplace; namespace ICSharpCode.SharpDevelop.Commands { @@ -74,33 +77,26 @@ namespace ICSharpCode.SharpDevelop.Commands } } - IMember FindBaseMember(IMember member) + IMember FindSimilarMember(IClass type, IMember member) { - IClass parentClass = member.DeclaringType; - IClass baseClass = parentClass.BaseClass; - if (baseClass == null) return null; if (member is IMethod) { IMethod parentMethod = (IMethod)member; - foreach (IClass childClass in baseClass.ClassInheritanceTree) { - foreach (IMethod m in childClass.Methods) { - if (string.Equals(parentMethod.Name, m.Name, StringComparison.InvariantCultureIgnoreCase)) { - if (m.IsStatic == parentMethod.IsStatic) { - if (DiffUtility.Compare(parentMethod.Parameters, m.Parameters) == 0) { - return m; - } + foreach (IMethod m in type.Methods) { + if (string.Equals(parentMethod.Name, m.Name, StringComparison.InvariantCultureIgnoreCase)) { + if (m.IsStatic == parentMethod.IsStatic) { + if (DiffUtility.Compare(parentMethod.Parameters, m.Parameters) == 0) { + return m; } } } } } else if (member is IProperty) { IProperty parentMethod = (IProperty)member; - foreach (IClass childClass in baseClass.ClassInheritanceTree) { - foreach (IProperty m in childClass.Properties) { - if (string.Equals(parentMethod.Name, m.Name, StringComparison.InvariantCultureIgnoreCase)) { - if (m.IsStatic == parentMethod.IsStatic) { - if (DiffUtility.Compare(parentMethod.Parameters, m.Parameters) == 0) { - return m; - } + foreach (IProperty m in type.Properties) { + if (string.Equals(parentMethod.Name, m.Name, StringComparison.InvariantCultureIgnoreCase)) { + if (m.IsStatic == parentMethod.IsStatic) { + if (DiffUtility.Compare(parentMethod.Parameters, m.Parameters) == 0) { + return m; } } } @@ -108,6 +104,20 @@ namespace ICSharpCode.SharpDevelop.Commands } return null; } + + IMember FindBaseMember(IMember member) + { + IClass parentClass = member.DeclaringType; + IClass baseClass = parentClass.BaseClass; + if (baseClass == null) return null; + + foreach (IClass childClass in baseClass.ClassInheritanceTree) { + IMember m = FindSimilarMember(childClass, member); + if (m != null) + return m; + } + return null; + } #endregion void Rename(object sender, EventArgs e) @@ -121,7 +131,33 @@ namespace ICSharpCode.SharpDevelop.Commands { MenuCommand item = (MenuCommand)sender; IMember member = (IMember)item.Tag; - MessageService.ShowMessage("Not implemented."); + List derivedClasses = RefactoringService.FindDerivedClasses(member.DeclaringType, ParserService.AllProjectContents); + List results = new List(); + foreach (IClass derivedClass in derivedClasses) { + if (derivedClass.CompilationUnit == null) continue; + if (derivedClass.CompilationUnit.FileName == null) continue; + IMember m = FindSimilarMember(derivedClass, member); + if (m != null && m.Region != null) { + SearchResult res = new SimpleSearchResult(m.FullyQualifiedName, new Point(m.Region.BeginColumn - 1, m.Region.BeginLine - 1)); + res.ProvidedDocumentInformation = GetDocumentInformation(derivedClass.CompilationUnit.FileName); + results.Add(res); + } + } + SearchReplaceInFilesManager.ShowSearchResults(results); + } + + ProvidedDocumentInformation GetDocumentInformation(string fileName) + { + foreach (IViewContent content in WorkbenchSingleton.Workbench.ViewContentCollection) { + if (content is ITextEditorControlProvider && + content.FileName != null && + FileUtility.IsEqualFile(content.FileName, fileName)) + { + return new ProvidedDocumentInformation(((ITextEditorControlProvider)content).TextEditorControl.Document, fileName, 0); + } + } + ITextBufferStrategy strategy = StringTextBufferStrategy.CreateTextBufferFromFile(fileName); + return new ProvidedDocumentInformation(strategy, fileName, 0); } void FindReferences(object sender, EventArgs e) diff --git a/src/Main/Base/Project/Src/Services/ParserService/CaseSensitiveProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/CaseSensitiveProjectContent.cs index 949146e71d..e592409efc 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/CaseSensitiveProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/CaseSensitiveProjectContent.cs @@ -77,6 +77,11 @@ namespace ICSharpCode.Core } } + public bool HasReferenceTo(IProjectContent content) + { + return referencedContents.Contains(content); + } + LanguageProperties language = LanguageProperties.CSharp; /// diff --git a/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs index 379c4cd280..5fc67bd08b 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs @@ -32,6 +32,8 @@ namespace ICSharpCode.Core get; } + bool HasReferenceTo(IProjectContent content); + /// /// Gets the properties of the language this project content was written in. /// diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 296bb296e9..ba9939ebc7 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -47,6 +47,12 @@ namespace ICSharpCode.Core } } + public static IEnumerable AllProjectContents { + get { + return projectContents.Values; + } + } + static IProjectContent forcedContent; /// /// Used for unit tests ONLY!! diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs new file mode 100644 index 0000000000..677f65c954 --- /dev/null +++ b/src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs @@ -0,0 +1,46 @@ +// +// +// +// +// +// + +using System; +using System.Collections.Generic; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.Core +{ + public static class RefactoringService + { + #region FindDerivedClasses + /// + /// Finds all classes deriving directly from baseClass. + /// + public static List FindDerivedClasses(IClass baseClass, IEnumerable projectContents) + { + string baseClassName = baseClass.Name; + string baseClassFullName = baseClass.FullyQualifiedName; + List list = new List(); + foreach (IProjectContent pc in projectContents) { + if (pc != baseClass.ProjectContent && !pc.HasReferenceTo(baseClass.ProjectContent)) { + // only project contents referencing the content of the base class + // can derive from the class + continue; + } + foreach (IClass c in pc.Classes) { + if (c.BaseTypes.Count == 0) continue; + string baseType = c.BaseTypes[0]; + if (pc.Language.NameComparer.Equals(baseType, baseClassName) || + pc.Language.NameComparer.Equals(baseType, baseClassFullName)) { + if (c.BaseClass.FullyQualifiedName == baseClass.FullyQualifiedName) { + list.Add(c); + } + } + } + } + return list; + } + #endregion + } +} diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/DocumentIterator/DirectoryDocumentIterator.cs b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/DocumentIterator/DirectoryDocumentIterator.cs index 409a3a3e29..8634023fb0 100644 --- a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/DocumentIterator/DirectoryDocumentIterator.cs +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/DocumentIterator/DirectoryDocumentIterator.cs @@ -59,9 +59,8 @@ namespace SearchAndReplace IDocument document; string fileName = files[curIndex].ToString(); foreach (IViewContent content in WorkbenchSingleton.Workbench.ViewContentCollection) { - // WINDOWS DEPENDENCY : ToUpper if (content.FileName != null && - Path.GetFullPath(content.FileName).ToUpper() == Path.GetFullPath(fileName).ToUpper()) { + FileUtility.IsEqualFile(content.FileName, fileName)) { document = ((ITextEditorControlProvider)content).TextEditorControl.Document; return new ProvidedDocumentInformation(document, fileName, diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceInFilesManager.cs b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceInFilesManager.cs index d5c2ce167a..cf2eb94bef 100644 --- a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceInFilesManager.cs +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchReplaceInFilesManager.cs @@ -56,6 +56,11 @@ namespace SearchAndReplace } static void FinishSearchInFiles(List results) + { + ShowSearchResults(results); + } + + public static void ShowSearchResults(List results) { PadDescriptor searchResultPanel = WorkbenchSingleton.Workbench.GetPad(typeof(SearchResultPanel)); if (searchResultPanel != null) { diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/SearchResult.cs b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/SearchResult.cs index d7b5910e78..2ca90a7958 100644 --- a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/SearchResult.cs +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Engine/SearchStrategy/SearchResult.cs @@ -61,12 +61,60 @@ namespace SearchAndReplace this.length = length; } + public virtual Point GetStartPosition(IDocument document) + { + return document.OffsetToPosition(Offset); + } + + public virtual Point GetEndPosition(IDocument document) + { + return document.OffsetToPosition(Offset + Length); + } + + /// + /// Gets a special text to display, or null to display the line's content. + /// + public virtual string DisplayText { + get { + return null; + } + } + public override string ToString() { - return String.Format("[DefaultLocation: FileName={0}, Offset={1}, Length={2}]", + return String.Format("[SearchResult: FileName={0}, Offset={1}, Length={2}]", FileName, Offset, Length); } } + + public class SimpleSearchResult : SearchResult + { + Point position; + + public override Point GetStartPosition(IDocument doc) + { + return position; + } + + public override Point GetEndPosition(IDocument doc) + { + return position; + } + + string displayText; + + public override string DisplayText { + get { + return displayText; + } + } + + public SimpleSearchResult(string displayText, Point position) : base(0, 0) + { + this.position = position; + this.displayText = displayText; + } + } } diff --git a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Pad/Nodes/SearchResultNode.cs b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Pad/Nodes/SearchResultNode.cs index c819d7c39b..55105ff32b 100644 --- a/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Pad/Nodes/SearchResultNode.cs +++ b/src/Main/Base/Project/Src/TextEditor/SearchAndReplace/Pad/Nodes/SearchResultNode.cs @@ -25,6 +25,7 @@ namespace SearchAndReplace Point startPosition; Point endPosition; string positionText; + string specialText; bool showFileName = false; public bool ShowFileName { get { @@ -33,13 +34,21 @@ namespace SearchAndReplace set { showFileName = value; if (showFileName) { - Text = positionText + document.GetText(line) + FileNameText; + Text = DisplayText + FileNameText; } else { - Text = positionText + document.GetText(line); + Text = DisplayText; } } } + string DisplayText { + get { + if (specialText != null) + return positionText + specialText; + else + return positionText + document.GetText(line).Replace("\t", " "); + } + } string FileNameText { get { return " in " + Path.GetFileName(result.FileName) + "(" + Path.GetDirectoryName(result.FileName) +")"; @@ -50,19 +59,19 @@ namespace SearchAndReplace drawDefault = false; this.document = document; this.result = result; - startPosition = document.OffsetToPosition(result.Offset); - endPosition = document.OffsetToPosition(result.Offset + result.Length); + startPosition = result.GetStartPosition(document); + endPosition = result.GetEndPosition(document); positionText = "(" + startPosition.Y + ", " + startPosition.X + ") "; line = document.GetLineSegment(startPosition.Y); - Text = positionText + document.GetText(line); + specialText = result.DisplayText; + Text = DisplayText; } protected override int MeasureItemWidth(DrawTreeNodeEventArgs e) { Graphics g = e.Graphics; - int x = MeasureTextWidth(g, positionText, BoldMonospacedFont); - x += MeasureTextWidth(g, document.GetText(line).Replace("\t", " "), BoldMonospacedFont); + int x = MeasureTextWidth(g, DisplayText, BoldMonospacedFont); if (ShowFileName) { x += MeasureTextWidth(g, FileNameText, ItalicFont); } @@ -76,8 +85,19 @@ namespace SearchAndReplace spaceSize = g.MeasureString("-", Font, new PointF(0, 0), StringFormat.GenericTypographic); - x += DrawLine(g, line, e.Bounds.Y, x); - + if (specialText != null) { + DrawText(g, specialText, Brushes.Black, Font, ref x, e.Bounds.Y); + } else { + x += DrawLine(g, line, e.Bounds.Y, x); + } + if (ShowFileName) { + x += DrawDocumentWord(g, + FileNameText, + new PointF(x, e.Bounds.Y), + ItalicMonospacedFont, + Color.Gray + ); + } } public override void ActivateItem() @@ -144,19 +164,11 @@ namespace SearchAndReplace } } else { xPos += DrawDocumentWord(g, - document.GetText(line), - new PointF(xPos, yPos), - MonospacedFont, - Color.Black - ); - } - if (ShowFileName) { - xPos += DrawDocumentWord(g, - FileNameText, - new PointF(xPos, yPos), - ItalicMonospacedFont, - Color.Gray - ); + document.GetText(line), + new PointF(xPos, yPos), + MonospacedFont, + Color.Black + ); } return xPos; }