Browse Source

first implementation of rename without proper UI

pull/45/merge
Siegfried Pammer 13 years ago
parent
commit
01df710105
  1. 93
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs
  2. 4
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs
  3. 3
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs
  4. 7
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs
  5. 22
      src/Main/Base/Project/Editor/Search/SearchResultMatch.cs
  6. 9
      src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
  7. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  8. 3
      src/Main/Base/Project/Parser/IParser.cs
  9. 3
      src/Main/Base/Project/Parser/IParserService.cs
  10. 31
      src/Main/Base/Project/Src/Editor/Commands/FindReferencesCommand.cs
  11. 44
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs
  12. 4
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
  13. 38
      src/Main/Base/Project/Src/Services/RefactoringService/Reference.cs
  14. 17
      src/Main/Base/Project/Src/Services/Tasks/Task.cs
  15. 3
      src/Main/SharpDevelop/Parser/ParserService.cs

93
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs

@ -8,6 +8,7 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.AvalonEdit.Document;
using CSharpBinding.Parser; using CSharpBinding.Parser;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core; using ICSharpCode.Core;
@ -99,7 +100,7 @@ namespace CSharpBinding
return; return;
ReadOnlyDocument document = null; ReadOnlyDocument document = null;
IHighlighter highlighter = null; IHighlighter highlighter = null;
List<Reference> results = new List<Reference>(); List<SearchResultMatch> results = new List<SearchResultMatch>();
// Grab the unresolved file matching the compilation version // Grab the unresolved file matching the compilation version
// (this may differ from the version created by re-parsing the project) // (this may differ from the version created by re-parsing the project)
@ -125,7 +126,7 @@ namespace CSharpBinding
int length = document.GetOffset(node.EndLocation) - offset; int length = document.GetOffset(node.EndLocation) - offset;
var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter); var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter);
var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null; var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null;
results.Add(new Reference(region, result, offset, length, builder, defaultTextColor)); results.Add(new SearchResultMatch(fileName, node.StartLocation, node.EndLocation, offset, length, builder, defaultTextColor));
}, cancellationToken); }, cancellationToken);
if (highlighter != null) { if (highlighter != null) {
highlighter.Dispose(); highlighter.Dispose();
@ -136,7 +137,93 @@ namespace CSharpBinding
public Task RenameAsync(SymbolRenameArgs args, Action<PatchedFile> callback, Action<Error> errorCallback) public Task RenameAsync(SymbolRenameArgs args, Action<PatchedFile> callback, Action<Error> errorCallback)
{ {
throw new NotImplementedException(); if (callback == null)
throw new ArgumentNullException("callback");
var cancellationToken = args.ProgressMonitor.CancellationToken;
return Task.Run(
() => {
bool isNameValid = true; // TODO : check name!
for (int i = 0; i < searchScopes.Count; i++) {
IFindReferenceSearchScope searchScope = searchScopes[i];
object progressLock = new object();
Parallel.ForEach(
interestingFileNames[i],
new ParallelOptions {
MaxDegreeOfParallelism = Environment.ProcessorCount,
CancellationToken = cancellationToken
},
delegate (string fileName) {
RenameReferencesInFile(args, searchScope, FileName.Create(fileName), callback, errorCallback, isNameValid, cancellationToken);
lock (progressLock)
args.ProgressMonitor.Progress += workAmountInverse;
});
}
}, cancellationToken
);
}
void RenameReferencesInFile(SymbolRenameArgs args, IFindReferenceSearchScope searchScope, FileName fileName, Action<PatchedFile> callback, Action<Error> errorCallback, bool isNameValid, CancellationToken cancellationToken)
{
ITextSource textSource = args.ParseableFileContentFinder.Create(fileName);
if (textSource == null)
return;
if (searchScope.SearchTerm != null) {
if (textSource.IndexOf(searchScope.SearchTerm, 0, textSource.TextLength, StringComparison.Ordinal) < 0)
return;
}
var parseInfo = SD.ParserService.Parse(fileName, textSource) as CSharpFullParseInformation;
if (parseInfo == null)
return;
ReadOnlyDocument document = null;
IHighlighter highlighter = null;
List<SearchResultMatch> results = new List<SearchResultMatch>();
// Grab the unresolved file matching the compilation version
// (this may differ from the version created by re-parsing the project)
CSharpUnresolvedFile unresolvedFile = null;
IProjectContent pc = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
if (pc != null) {
unresolvedFile = pc.GetFile(fileName) as CSharpUnresolvedFile;
}
CSharpAstResolver resolver = new CSharpAstResolver(compilation, parseInfo.SyntaxTree, unresolvedFile);
fr.RenameReferencesInFile(
new[] { searchScope }, args.NewName, resolver,
delegate (RenameCallbackArguments callbackArgs) {
var node = callbackArgs.NodeToReplace;
if (document == null) {
document = new ReadOnlyDocument(textSource, fileName);
highlighter = SD.EditorControlService.CreateHighlighter(document);
highlighter.BeginHighlighting();
}
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) {
highlighter.Dispose();
}
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));
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);
}
callback(new PatchedFile(fileName, results, oldVersion, changedDocument.Version));
}
} }
} }
} }

4
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs

@ -149,7 +149,7 @@ namespace CSharpBinding.Parser
return ResolveAtLocation.Resolve(compilation, csParseInfo.UnresolvedFile, csParseInfo.SyntaxTree, location, cancellationToken); return ResolveAtLocation.Resolve(compilation, csParseInfo.UnresolvedFile, csParseInfo.SyntaxTree, location, cancellationToken);
} }
public void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action<Reference> callback, CancellationToken cancellationToken) public void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action<SearchResultMatch> callback, CancellationToken cancellationToken)
{ {
var csParseInfo = parseInfo as CSharpFullParseInformation; var csParseInfo = parseInfo as CSharpFullParseInformation;
if (csParseInfo == null) if (csParseInfo == null)
@ -171,7 +171,7 @@ namespace CSharpBinding.Parser
int length = document.GetOffset(node.EndLocation) - offset; int length = document.GetOffset(node.EndLocation) - offset;
var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter); var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter);
var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null; var defaultTextColor = highlighter != null ? highlighter.DefaultTextColor : null;
callback(new Reference(region, result, offset, length, builder, defaultTextColor)); callback(new SearchResultMatch(parseInfo.FileName, node.StartLocation, node.EndLocation, offset, length, builder, defaultTextColor));
}, cancellationToken); }, cancellationToken);
if (highlighter != null) { if (highlighter != null) {

3
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs

@ -18,6 +18,7 @@ using ICSharpCode.NRefactory.Utils;
using ICSharpCode.NRefactory.Xml; using ICSharpCode.NRefactory.Xml;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
@ -104,7 +105,7 @@ namespace ICSharpCode.XamlBinding
.ResolveAtLocation(location, cancellationToken); .ResolveAtLocation(location, cancellationToken);
} }
public void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action<Reference> callback, CancellationToken cancellationToken) public void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action<SearchResultMatch> callback, CancellationToken cancellationToken)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

7
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs

@ -87,7 +87,7 @@ namespace ICSharpCode.XamlBinding
return; return;
ReadOnlyDocument document = null; ReadOnlyDocument document = null;
IHighlighter highlighter = null; IHighlighter highlighter = null;
List<Reference> results = new List<Reference>(); List<SearchResultMatch> results = new List<SearchResultMatch>();
XamlAstResolver resolver = new XamlAstResolver(compilation, parseInfo); XamlAstResolver resolver = new XamlAstResolver(compilation, parseInfo);
do { do {
if (document == null) { if (document == null) {
@ -100,7 +100,7 @@ namespace ICSharpCode.XamlBinding
if ((result is TypeResolveResult && ((TypeResolveResult)result).Type.Equals(entity)) || (result is MemberResolveResult && ((MemberResolveResult)result).Member.Equals(entity))) { if ((result is TypeResolveResult && ((TypeResolveResult)result).Type.Equals(entity)) || (result is MemberResolveResult && ((MemberResolveResult)result).Member.Equals(entity))) {
var region = new DomRegion(fileName, document.GetLocation(offset), document.GetLocation(offset + length)); var region = new DomRegion(fileName, document.GetLocation(offset), document.GetLocation(offset + length));
var builder = SearchResultsPad.CreateInlineBuilder(region.Begin, region.End, document, highlighter); var builder = SearchResultsPad.CreateInlineBuilder(region.Begin, region.End, document, highlighter);
results.Add(new Reference(region, result, offset, length, builder, highlighter.DefaultTextColor)); results.Add(new SearchResultMatch(fileName, document.GetLocation(offset), document.GetLocation(offset + length), offset, length, builder, highlighter.DefaultTextColor));
} }
offset = textSource.IndexOf(entity.Name, offset + length, textSource.TextLength - offset - length, StringComparison.OrdinalIgnoreCase); offset = textSource.IndexOf(entity.Name, offset + length, textSource.TextLength - offset - length, StringComparison.OrdinalIgnoreCase);
} while (offset > 0); } while (offset > 0);
@ -113,7 +113,8 @@ namespace ICSharpCode.XamlBinding
public Task RenameAsync(SymbolRenameArgs args, Action<PatchedFile> callback, Action<Error> errorCallback) public Task RenameAsync(SymbolRenameArgs args, Action<PatchedFile> callback, Action<Error> errorCallback)
{ {
throw new NotImplementedException(); // TODO implement Rename for XAML
return Task.Run(() => {});
} }
} }
} }

22
src/Main/Base/Project/Editor/Search/SearchResultMatch.cs

@ -156,26 +156,24 @@ namespace ICSharpCode.SharpDevelop.Editor.Search
public class PatchedFile : SearchedFile public class PatchedFile : SearchedFile
{ {
ITextSourceVersion result; ITextSourceVersion oldVersion;
ITextSourceVersion newVersion;
public PatchedFile(FileName fileName, IReadOnlyList<SearchResultMatch> matches, ITextSourceVersion result) public PatchedFile(FileName fileName, IReadOnlyList<SearchResultMatch> matches, ITextSourceVersion oldVersion, ITextSourceVersion newVersion)
: base(fileName, matches) : base(fileName, matches)
{ {
if (result == null) if (oldVersion == null)
throw new ArgumentNullException("result"); throw new ArgumentNullException("oldVersion");
this.result = result; if (newVersion == null)
throw new ArgumentNullException("newVersion");
this.oldVersion = oldVersion;
this.newVersion = newVersion;
} }
public void Apply(IDocument document) public void Apply(IDocument document)
{ {
ITextSourceVersion oldVersion = document.Version;
if (oldVersion == null)
throw new InvalidOperationException("Document is unversioned, cannot apply changes!");
if (!result.BelongsToSameDocumentAs(oldVersion))
throw new InvalidOperationException("Patch does not belong to this document!");
using (document.OpenUndoGroup()) { using (document.OpenUndoGroup()) {
var changes = oldVersion.GetChangesTo(result); var changes = oldVersion.GetChangesTo(newVersion);
foreach (var change in changes) foreach (var change in changes)
document.Replace(change.Offset, change.RemovalLength, change.InsertedText); document.Replace(change.Offset, change.RemovalLength, change.InsertedText);
} }

9
src/Main/Base/Project/ICSharpCode.SharpDevelop.addin

@ -1262,7 +1262,7 @@
class = "ICSharpCode.SharpDevelop.Gui.OptionPanels.SelectCulturePanel"/> class = "ICSharpCode.SharpDevelop.Gui.OptionPanels.SelectCulturePanel"/>
<OptionPanel id = "SelectStyle" <OptionPanel id = "SelectStyle"
label = "${res:Dialog.Options.IDEOptions.SelectVisualStyle.PanelName}" label = "${res:Dialog.Options.IDEOptions.SelectVisualStyle.PanelName}"
class = "ICSharpCode.SharpDevelop.Gui.OptionPanels.SelectStylePanel"/> class = "ICSharpCode.SharpDevelop.Gui.OptionPanels.SelectStylePanel"/>
<OptionPanel id = "LoadSave" <OptionPanel id = "LoadSave"
label = "${res:Dialog.Options.IDEOptions.LoadSaveOptions.PanelName}" label = "${res:Dialog.Options.IDEOptions.LoadSaveOptions.PanelName}"
class = "ICSharpCode.SharpDevelop.OptionPanels.LoadSaveOptions"/> class = "ICSharpCode.SharpDevelop.OptionPanels.LoadSaveOptions"/>
@ -1296,7 +1296,7 @@
<OptionPanel id = "ToolsOptions" <OptionPanel id = "ToolsOptions"
label = "${res:Dialog.Options.IDEOptions.ToolsOptionsText}"> label = "${res:Dialog.Options.IDEOptions.ToolsOptionsText}">
<OptionPanel id = "ExternalTools" <OptionPanel id = "ExternalTools"
label = "${res:Dialog.Options.ExternalToolsText}" label = "${res:Dialog.Options.ExternalToolsText}"
class = "ICSharpCode.SharpDevelop.Gui.OptionPanels.ExternalToolPanel"/> class = "ICSharpCode.SharpDevelop.Gui.OptionPanels.ExternalToolPanel"/>
@ -1841,6 +1841,11 @@
icon="Icons.16x16.SelectionArrow" icon="Icons.16x16.SelectionArrow"
class = "ICSharpCode.SharpDevelop.Editor.Commands.FindReferencesCommand"/> class = "ICSharpCode.SharpDevelop.Editor.Commands.FindReferencesCommand"/>
<MenuItem id = "Rename"
label = "${res:SharpDevelop.Refactoring.RenameCommand}"
shortcut="Ctrl+R"
class = "ICSharpCode.SharpDevelop.Editor.Commands.RenameSymbolCommand"/>
<MenuItem id = "GotoBrace" <MenuItem id = "GotoBrace"
label = "${res:XML.MainMenu.SearchMenu.GotoBrace}" label = "${res:XML.MainMenu.SearchMenu.GotoBrace}"
shortcut = "Control|B" shortcut = "Control|B"

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -735,7 +735,6 @@
<SubType>Component</SubType> <SubType>Component</SubType>
</Compile> </Compile>
<Compile Include="Src\Services\RefactoringService\RefactoringService.cs" /> <Compile Include="Src\Services\RefactoringService\RefactoringService.cs" />
<Compile Include="Src\Services\RefactoringService\Reference.cs" />
<Compile Include="Src\Services\ProjectService\ParseableFileContentFinder.cs" /> <Compile Include="Src\Services\ProjectService\ParseableFileContentFinder.cs" />
<Compile Include="Src\Project\Items\ImportProjectItem.cs" /> <Compile Include="Src\Project\Items\ImportProjectItem.cs" />
<Compile Include="Src\Services\Debugger\CurrentLineBookmark.cs" /> <Compile Include="Src\Services\Debugger\CurrentLineBookmark.cs" />

3
src/Main/Base/Project/Parser/IParser.cs

@ -10,6 +10,7 @@ using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
@ -62,7 +63,7 @@ namespace ICSharpCode.SharpDevelop.Parser
ResolveResult ResolveSnippet(ParseInformation parseInfo, TextLocation location, string codeSnippet, ICompilation compilation, CancellationToken cancellationToken); ResolveResult ResolveSnippet(ParseInformation parseInfo, TextLocation location, string codeSnippet, ICompilation compilation, CancellationToken cancellationToken);
void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action<Reference> callback, CancellationToken cancellationToken); void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action<SearchResultMatch> callback, CancellationToken cancellationToken);
/// <summary> /// <summary>
/// Creates a compilation for a single file that does not belong to any project. /// Creates a compilation for a single file that does not belong to any project.

3
src/Main/Base/Project/Parser/IParserService.cs

@ -12,6 +12,7 @@ using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
@ -230,7 +231,7 @@ namespace ICSharpCode.SharpDevelop.Parser
ITextSource fileContent = null, ICompilation compilation = null, ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken)); CancellationToken cancellationToken = default(CancellationToken));
Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<Reference> callback, Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<SearchResultMatch> callback,
ITextSource fileContent = null, ICompilation compilation = null, ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken)); CancellationToken cancellationToken = default(CancellationToken));
#endregion #endregion

31
src/Main/Base/Project/Src/Editor/Commands/FindReferencesCommand.cs

@ -4,6 +4,7 @@
using System; using System;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Editor.Commands namespace ICSharpCode.SharpDevelop.Editor.Commands
@ -34,10 +35,38 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
public override void Run(ResolveResult symbol) public override void Run(ResolveResult symbol)
{ {
var entity = GetEntity(symbol); var entity = GetEntity(symbol);
string title = "${res:SharpDevelop.Refactoring.Rename}";
string text = title; // TODO add proper text
if (entity != null) { if (entity != null) {
//FindReferenceService.RenameSymbol(entity, switch (entity.SymbolKind) {
case ICSharpCode.NRefactory.TypeSystem.SymbolKind.TypeDefinition:
text = "${res:SharpDevelop.Refactoring.RenameClassText}";
break;
default:
text = "${res:SharpDevelop.Refactoring.RenameMemberText}";
break;
}
string newName = SD.MessageService.ShowInputBox(title, text, entity.Name);
if (newName != entity.Name) {
if (!CheckName(newName)) {
SD.MessageService.ShowError("The symbol cannot be renamed because its new name is invalid!");
return;
}
using (IProgressMonitor progressMonitor = AsynchronousWaitDialog.ShowWaitDialog("${res:SharpDevelop.Refactoring.Rename}"))
FindReferenceService.RenameSymbol(entity, newName, progressMonitor)
.ObserveOnUIThread()
.Subscribe(error => SD.MessageService.ShowError(error.Message), ex => SD.MessageService.ShowException(ex), () => {});
}
} }
} }
bool CheckName(string name)
{
// TODO implement for current language!
return !string.IsNullOrWhiteSpace(name);
}
} }
} }

44
src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs

@ -12,6 +12,7 @@ using ICSharpCode.NRefactory.Analysis;
using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.Search; using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -109,7 +110,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
if (progressMonitor == null) if (progressMonitor == null)
throw new ArgumentNullException("progressMonitor"); throw new ArgumentNullException("progressMonitor");
var fileName = FileName.Create(variable.Region.FileName); var fileName = FileName.Create(variable.Region.FileName);
List<Reference> references = new List<Reference>(); List<SearchResultMatch> references = new List<SearchResultMatch>();
await SD.ParserService.FindLocalReferencesAsync( await SD.ParserService.FindLocalReferencesAsync(
fileName, variable, fileName, variable,
r => { lock (references) references.Add(r); }, r => { lock (references) references.Add(r); },
@ -186,7 +187,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
} }
#endregion #endregion
public static IReadOnlyList<Error> RenameSymbol(ISymbol symbol, IProgressMonitor progressMonitor) public static async Task RenameSymbolAsync(ISymbol symbol, string newName, IProgressMonitor progressMonitor, Action<Error> errorCallback)
{ {
if (symbol == null) if (symbol == null)
throw new ArgumentNullException("symbol"); throw new ArgumentNullException("symbol");
@ -197,33 +198,49 @@ namespace ICSharpCode.SharpDevelop.Refactoring
progressMonitor.ShowingDialog = true; progressMonitor.ShowingDialog = true;
MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}"); MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
progressMonitor.ShowingDialog = false; progressMonitor.ShowingDialog = false;
return EmptyList<Error>.Instance; return;
} }
double totalWorkAmount; double totalWorkAmount;
List<ISymbolSearch> symbolSearches = PrepareSymbolSearch(symbol, progressMonitor.CancellationToken, out totalWorkAmount); List<ISymbolSearch> symbolSearches = PrepareSymbolSearch(symbol, progressMonitor.CancellationToken, out totalWorkAmount);
double workDone = 0; double workDone = 0;
ParseableFileContentFinder parseableFileContentFinder = new ParseableFileContentFinder(); ParseableFileContentFinder parseableFileContentFinder = new ParseableFileContentFinder();
var errors = new List<Error>(); var errors = new List<Error>();
var changes = new List<PatchedFile>();
foreach (ISymbolSearch s in symbolSearches) { foreach (ISymbolSearch s in symbolSearches) {
progressMonitor.CancellationToken.ThrowIfCancellationRequested(); progressMonitor.CancellationToken.ThrowIfCancellationRequested();
using (var childProgressMonitor = progressMonitor.CreateSubTask(s.WorkAmount / totalWorkAmount)) { using (var childProgressMonitor = progressMonitor.CreateSubTask(s.WorkAmount / totalWorkAmount)) {
s.RenameAsync(new SymbolRenameArgs(childProgressMonitor, parseableFileContentFinder), await s.RenameAsync(new SymbolRenameArgs(newName, childProgressMonitor, parseableFileContentFinder),
ApplyChanges, error => errors.Add(error)).FireAndForget(); file => changes.Add(file), error => errors.Add(error));
} }
workDone += s.WorkAmount; workDone += s.WorkAmount;
progressMonitor.Progress = workDone / totalWorkAmount; progressMonitor.Progress = workDone / totalWorkAmount;
} }
return errors; if (errors.Count == 0) {
foreach (var file in changes) {
ApplyChanges(file);
}
} else {
foreach (var error in errors) {
errorCallback(error);
}
}
}
public static IObservable<Error> RenameSymbol(ISymbol symbol, string newName, IProgressMonitor progressMonitor)
{
return ReactiveExtensions.CreateObservable<Error>(
(monitor, callback) => RenameSymbolAsync(symbol, newName, monitor, callback),
progressMonitor);
} }
static void ApplyChanges(PatchedFile file) static void ApplyChanges(PatchedFile file)
{ {
var view = SD.FileService.OpenFile(file.FileName, false); var view = SD.FileService.OpenFile(file.FileName, false);
IDocument document = view.GetService(typeof(IDocument)) as IDocument; ITextEditor editor = view.GetService(typeof(ITextEditor)) as ITextEditor;
if (document == null) if (editor == null)
throw new InvalidOperationException("Document not found!"); throw new InvalidOperationException("Editor/document not found!");
file.Apply(document); file.Apply(editor.Document);
} }
} }
@ -250,10 +267,15 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public class SymbolRenameArgs : SymbolSearchArgs public class SymbolRenameArgs : SymbolSearchArgs
{ {
public SymbolRenameArgs(IProgressMonitor progressMonitor, ParseableFileContentFinder parseableFileContentFinder) public SymbolRenameArgs(string newName, IProgressMonitor progressMonitor, ParseableFileContentFinder parseableFileContentFinder)
: base(progressMonitor, parseableFileContentFinder) : base(progressMonitor, parseableFileContentFinder)
{ {
if (newName == null)
throw new ArgumentNullException("newName");
NewName = newName;
} }
public string NewName { get; private set; }
} }
public interface ISymbolSearch public interface ISymbolSearch

4
src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs

@ -337,7 +337,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
*/ */
[Obsolete] [Obsolete]
public static void ShowAsSearchResults(string title, List<Reference> list) public static void ShowAsSearchResults(string title, List<SearchResultMatch> list)
{ {
if (list == null) return; if (list == null) return;
List<SearchResultMatch> results = new List<SearchResultMatch>(list.Count); List<SearchResultMatch> results = new List<SearchResultMatch>(list.Count);
@ -345,7 +345,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
ITextSource buffer = null; ITextSource buffer = null;
FileName fileName = null; FileName fileName = null;
IHighlighter highlighter = null; IHighlighter highlighter = null;
foreach (Reference r in list) { foreach (SearchResultMatch r in list) {
if (document == null || fileName != r.FileName) { if (document == null || fileName != r.FileName) {
if (highlighter != null) { if (highlighter != null) {
highlighter.Dispose(); highlighter.Dispose();

38
src/Main/Base/Project/Src/Services/RefactoringService/Reference.cs

@ -1,38 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor.Search;
namespace ICSharpCode.SharpDevelop.Refactoring
{
/// <summary>
/// A reference to a class or class member.
/// </summary>
public class Reference : SearchResultMatch
{
// TODO: this looks like a memory usage problem
// SearchResultMatch is kept alive for a long time (list of previous searches),
// but ResolveResult keeps the whole compilation alive
// We might have to split Reference/SearchResultMatch into separate instances
ResolveResult resolveResult;
public Reference(DomRegion region, ResolveResult resolveResult, int offset, int length, HighlightedInlineBuilder builder, HighlightingColor defaultTextColor)
: base(FileName.Create(region.FileName), region.Begin, region.End, offset, length, builder, defaultTextColor)
{
if (region.IsEmpty)
throw new ArgumentException("Region must not be empty");
if (resolveResult == null)
throw new ArgumentNullException("resolveResult");
this.resolveResult = resolveResult;
}
public ResolveResult ResolveResult {
get { return resolveResult; }
}
}
}

17
src/Main/Base/Project/Src/Services/Tasks/Task.cs

@ -3,6 +3,7 @@
using System; using System;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
@ -156,6 +157,22 @@ namespace ICSharpCode.SharpDevelop
this.BuildError = error; this.BuildError = error;
} }
public SDTask(Error error)
{
if (error == null)
throw new ArgumentNullException("error");
switch (error.ErrorType) {
case ErrorType.Error:
type = TaskType.Error;
break;
case ErrorType.Warning:
type = TaskType.Warning;
break;
}
description = error.Message;
//hasLocation = !error.Region.IsEmpty;
}
public void JumpToPosition() public void JumpToPosition()
{ {
if (hasLocation && !position.IsDeleted) if (hasLocation && !position.IsDeleted)

3
src/Main/SharpDevelop/Parser/ParserService.cs

@ -15,6 +15,7 @@ using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
@ -308,7 +309,7 @@ namespace ICSharpCode.SharpDevelop.Parser
}, cancellationToken); }, cancellationToken);
} }
public async Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<Reference> callback, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken) public async Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<SearchResultMatch> callback, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{ {
var entry = GetFileEntry(fileName, true); var entry = GetFileEntry(fileName, true);
if (entry.parser == null) if (entry.parser == null)

Loading…
Cancel
Save