diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs index 5aaea4a650..8d143a3e5f 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs @@ -8,10 +8,12 @@ using System.Linq; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using ICSharpCode.AvalonEdit.Document; + using CSharpBinding.Parser; +using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Core; +using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.TypeSystem; @@ -142,7 +144,7 @@ namespace CSharpBinding var cancellationToken = args.ProgressMonitor.CancellationToken; return Task.Run( () => { - bool isNameValid = true; // TODO : check name! + bool isNameValid = Mono.CSharp.Tokenizer.IsValidIdentifier(args.NewName); for (int i = 0; i < searchScopes.Count; i++) { IFindReferenceSearchScope searchScope = searchScopes[i]; object progressLock = new object(); @@ -177,7 +179,7 @@ namespace CSharpBinding return; ReadOnlyDocument document = null; IHighlighter highlighter = null; - List results = new List(); + List results = new List(); // Grab the unresolved file matching the compilation version // (this may differ from the version created by re-parsing the project) @@ -193,20 +195,26 @@ namespace CSharpBinding new[] { searchScope }, args.NewName, resolver, delegate (RenameCallbackArguments callbackArgs) { var node = callbackArgs.NodeToReplace; + string newCode = callbackArgs.NewNode.ToString(); if (document == null) { document = new ReadOnlyDocument(textSource, fileName); - highlighter = SD.EditorControlService.CreateHighlighter(document); - highlighter.BeginHighlighting(); + + if (args.ProvideHighlightedLine) { + highlighter = SD.EditorControlService.CreateHighlighter(document); + highlighter.BeginHighlighting(); + } + } + var startLocation = node.StartLocation; + var endLocation = node.EndLocation; + int offset = document.GetOffset(startLocation); + int length = document.GetOffset(endLocation) - offset; + if (args.ProvideHighlightedLine) { + var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter); + var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null; + results.Add(new RenameResultMatch(fileName, startLocation, endLocation, offset, length, newCode, builder, defaultTextColor)); + } else { + results.Add(new RenameResultMatch(fileName, startLocation, endLocation, offset, length, newCode)); } - Identifier identifier = node.GetChildByRole(Roles.Identifier); - if (!identifier.IsNull) - node = identifier; - var region = new DomRegion(fileName, node.StartLocation, node.EndLocation); - int offset = document.GetOffset(node.StartLocation); - int length = document.GetOffset(node.EndLocation) - offset; - var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter); - var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null; - results.Add(new SearchResultMatch(fileName, node.StartLocation, node.EndLocation, offset, length, builder, defaultTextColor)); }, errorCallback, cancellationToken); if (highlighter != null) { @@ -214,16 +222,28 @@ namespace CSharpBinding } if (results.Count > 0) { if (!isNameValid) { - errorCallback(new Error(ErrorType.Error, string.Format("The name '{0}' is not valid in the current context!", args.NewName), 0, 0)); + errorCallback(new Error(ErrorType.Error, string.Format("The name '{0}' is not valid in the current context!", args.NewName), + new DomRegion(fileName, results[0].StartLocation))); return; } IDocument changedDocument = new TextDocument(document); var oldVersion = changedDocument.Version; foreach (var result in results.OrderByDescending(m => m.StartOffset)) { - changedDocument.Replace(result.StartOffset, result.Length, args.NewName); + changedDocument.Replace(result.StartOffset, result.Length, result.newCode); } callback(new PatchedFile(fileName, results, oldVersion, changedDocument.Version)); } } + + class RenameResultMatch : SearchResultMatch + { + internal readonly string newCode; + + public RenameResultMatch(FileName fileName, TextLocation startLocation, TextLocation endLocation, int offset, int length, string newCode, HighlightedInlineBuilder builder = null, HighlightingColor defaultTextColor = null) + : base(fileName, startLocation, endLocation, offset, length, builder, defaultTextColor) + { + this.newCode = newCode; + } + } } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs index a60ef9e2ba..32717a2666 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeGenerator.cs @@ -127,7 +127,12 @@ namespace CSharpBinding.Refactoring fieldDecl.Variables.Add(new VariableInitializer(name)); script.InsertWithCursor("Add field: " + name, Script.InsertPosition.End, fieldDecl); } - base.AddField(declaringType, accessibility, fieldType, name); + } + + public override void ChangeAccessibility(IEntity entity, Accessibility newAccessiblity) + { + // TODO script.ChangeModifiers(...) + throw new NotImplementedException(); } } } diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs index 1f0afa1037..e892641910 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs @@ -500,15 +500,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return null; } - if (node is TypeDeclaration) + if (node is TypeDeclaration) node = ((TypeDeclaration)node).NameToken; - if (node is DelegateDeclaration) + if (node is DelegateDeclaration) node = ((DelegateDeclaration)node).NameToken; - if (node is EntityDeclaration) + if (node is EntityDeclaration) node = ((EntityDeclaration)node).NameToken; - if (node is ParameterDeclaration) + if (node is ParameterDeclaration) node = ((ParameterDeclaration)node).NameToken; if (node is ConstructorDeclaration) node = ((ConstructorDeclaration)node).NameToken; @@ -531,8 +531,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Action callback, Action errorCallback, CancellationToken cancellationToken = default (CancellationToken)) { FindReferencesInFile( - searchScopes, - resolver, + searchScopes, + resolver, delegate(AstNode astNode, ResolveResult result) { var nodeToReplace = GetNodeToReplace(astNode); if (nodeToReplace == null) { @@ -540,7 +540,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return; } callback (new RenameCallbackArguments(nodeToReplace, Identifier.Create(newName))); - }, + }, cancellationToken); } #endregion diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs index e65831a17e..1c6da27bb1 100644 --- a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs @@ -166,6 +166,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets whether this member is declared to be shadowing another member with the same name. + /// (C# 'new' keyword) /// bool IsShadowing { get; } diff --git a/src/Main/Base/Project/Dom/IEntityModel.cs b/src/Main/Base/Project/Dom/IEntityModel.cs index ed122ccd32..13946955bf 100644 --- a/src/Main/Base/Project/Dom/IEntityModel.cs +++ b/src/Main/Base/Project/Dom/IEntityModel.cs @@ -37,6 +37,12 @@ namespace ICSharpCode.SharpDevelop.Dom /// Static classes also count as sealed classes. bool IsSealed { get; } + /// + /// Gets whether this member is declared to be shadowing another member with the same name. + /// (C# 'new' keyword) + /// + bool IsShadowing { get; } + /// /// Resolves the entity in the current solution snapshot. /// Returns null if the entity could not be resolved. diff --git a/src/Main/Base/Project/Dom/IMemberModel.cs b/src/Main/Base/Project/Dom/IMemberModel.cs index b213e0fb83..10c79d5be2 100644 --- a/src/Main/Base/Project/Dom/IMemberModel.cs +++ b/src/Main/Base/Project/Dom/IMemberModel.cs @@ -28,5 +28,21 @@ namespace ICSharpCode.SharpDevelop.Dom /// Updates the member model with the specified new member. /// void Update(IUnresolvedMember newMember); + + /// + /// Gets if the member is virtual. Is true only if the "virtual" modifier was used, but non-virtual + /// members can be overridden, too; if they are abstract or overriding a method. + /// + bool IsVirtual { get; } + + /// + /// Gets whether this member is overriding another member. + /// + bool IsOverride { get; } + + /// + /// Gets if the member can be overridden. Returns true when the member is "abstract", "virtual" or "override" but not "sealed". + /// + bool IsOverridable { get; } } } diff --git a/src/Main/Base/Project/Dom/IMethodModel.cs b/src/Main/Base/Project/Dom/IMethodModel.cs index ecc11a80ca..ef39dd85a2 100644 --- a/src/Main/Base/Project/Dom/IMethodModel.cs +++ b/src/Main/Base/Project/Dom/IMethodModel.cs @@ -7,6 +7,6 @@ namespace ICSharpCode.SharpDevelop.Dom { public interface IMethodModel : IMemberModel { - + int TypeParameterCount { get; } } } diff --git a/src/Main/Base/Project/Refactoring/CodeGenerator.cs b/src/Main/Base/Project/Refactoring/CodeGenerator.cs index 2143a49cb7..c47e7889d5 100644 --- a/src/Main/Base/Project/Refactoring/CodeGenerator.cs +++ b/src/Main/Base/Project/Refactoring/CodeGenerator.cs @@ -81,5 +81,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring { throw new NotSupportedException("Feature not supported!"); } + + public virtual void MakeVirtual(IMember member) + { + throw new NotSupportedException("Feature not supported!"); + } } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs index 0ad760a42a..298cf6097c 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs @@ -209,8 +209,9 @@ namespace ICSharpCode.SharpDevelop.Refactoring foreach (ISymbolSearch s in symbolSearches) { progressMonitor.CancellationToken.ThrowIfCancellationRequested(); using (var childProgressMonitor = progressMonitor.CreateSubTask(s.WorkAmount / totalWorkAmount)) { - await s.RenameAsync(new SymbolRenameArgs(newName, childProgressMonitor, parseableFileContentFinder), - file => changes.Add(file), error => errors.Add(error)); + var args = new SymbolRenameArgs(newName, childProgressMonitor, parseableFileContentFinder); + args.ProvideHighlightedLine = false; + await s.RenameAsync(args, file => changes.Add(file), error => errors.Add(error)); } workDone += s.WorkAmount; @@ -252,6 +253,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring get { return this.ProgressMonitor.CancellationToken; } } + /// + /// Specifies whether the symbol search should pass a HighlightedInlineBuilder + /// for the matching line to the SearchResultMatch. + /// The default value is true. + /// + public bool ProvideHighlightedLine { get; set; } + public ParseableFileContentFinder ParseableFileContentFinder { get; private set; } public SymbolSearchArgs(IProgressMonitor progressMonitor, ParseableFileContentFinder parseableFileContentFinder) @@ -262,6 +270,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring throw new ArgumentNullException("parseableFileContentFinder"); this.ProgressMonitor = progressMonitor; this.ParseableFileContentFinder = parseableFileContentFinder; + this.ProvideHighlightedLine = true; } } diff --git a/src/Main/SharpDevelop/Dom/MemberModel.cs b/src/Main/SharpDevelop/Dom/MemberModel.cs index f4aa39519a..48a2b79861 100644 --- a/src/Main/SharpDevelop/Dom/MemberModel.cs +++ b/src/Main/SharpDevelop/Dom/MemberModel.cs @@ -106,5 +106,21 @@ namespace ICSharpCode.SharpDevelop.Dom public bool IsSealed { get { return member.IsSealed; } } + + public bool IsShadowing { + get { return member.IsShadowing; } + } + + public bool IsVirtual { + get { return member.IsVirtual; } + } + + public bool IsOverride { + get { return member.IsOverride; } + } + + public bool IsOverridable { + get { return member.IsOverridable; } + } } } diff --git a/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs b/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs index 6ba5769a8a..62ea575d1b 100644 --- a/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs +++ b/src/Main/SharpDevelop/Dom/TypeDefinitionModel.cs @@ -330,5 +330,9 @@ namespace ICSharpCode.SharpDevelop.Dom public bool IsSealed { get { return parts.Any(p => p.IsSealed); } } + + public bool IsShadowing { + get { return parts.Any(p => p.IsShadowing); } + } } }