Browse Source

Add support for simple context actions.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
50e9489c07
  1. 10
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 6
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  3. 38
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpContextActionDoozer.cs
  4. 158
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs
  5. 83
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs
  6. 123
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/SDRefactoringContext.cs
  7. 2
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextAction.cs
  8. 2
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionViewModel.cs
  9. 7
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/EditorContext.cs
  10. 3
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextAction.cs
  11. 4
      src/Main/Base/Project/Src/Services/RefactoringService/GoToEntityAction.cs

10
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin

@ -10,7 +10,7 @@
<Runtime> <Runtime>
<Import assembly = "CSharpBinding.dll"> <Import assembly = "CSharpBinding.dll">
<Doozer name="CSharpContextAction" class="CSharpBinding.CSharpContextActionDoozer"/> <Doozer name="CSharpContextAction" class="CSharpBinding.Refactoring.CSharpContextActionDoozer"/>
</Import> </Import>
<Import assembly = ":ICSharpCode.SharpDevelop"/> <Import assembly = ":ICSharpCode.SharpDevelop"/>
<Import assembly = ":ICSharpCode.NRefactory.CSharp"/> <Import assembly = ":ICSharpCode.NRefactory.CSharp"/>
@ -156,7 +156,7 @@
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateGetter" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateGetter" />
<!--<CSharpContextAction id = "GenerateProperty" <!--<CSharpContextAction id = "GenerateProperty"
displayName = "Generate property" displayName = "Generate property"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateProperty" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateProperty" />-->
<CSharpContextAction id = "GenerateSwitchLabels" <CSharpContextAction id = "GenerateSwitchLabels"
displayName = "Generate switch labels" displayName = "Generate switch labels"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateSwitchLabels" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateSwitchLabels" />
@ -175,9 +175,9 @@
<CSharpContextAction id = "RemoveBraces" <CSharpContextAction id = "RemoveBraces"
displayName = "Remove braces" displayName = "Remove braces"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBraces" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBraces" />
<CSharpContextAction id = "RemoveRegion" <!--<CSharpContextAction id = "RemoveRegion"
displayName = "Remove #region" displayName = "Remove #region"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRegion" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRegion" />-->
<CSharpContextAction id = "ReplaceEmptyString" <CSharpContextAction id = "ReplaceEmptyString"
displayName = "Use string.Empty" displayName = "Use string.Empty"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceEmptyString" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceEmptyString" />
@ -192,6 +192,6 @@
class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseExplicitType" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseExplicitType" />
<CSharpContextAction id = "UseVarKeyword" <CSharpContextAction id = "UseVarKeyword"
displayName = "Use 'var' keyword" displayName = "Use 'var' keyword"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeyword" />--> class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeyword" />
</Path> </Path>
</AddIn> </AddIn>

6
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -66,6 +66,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\AssemblyInfo.cs" /> <Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\Refactoring\SDScript.cs" />
<EmbeddedResource Include="Resources\BuildOptions.xfrm" /> <EmbeddedResource Include="Resources\BuildOptions.xfrm" />
<EmbeddedResource Include="Resources\MyNamespaceSupportForCSharp.cs" /> <EmbeddedResource Include="Resources\MyNamespaceSupportForCSharp.cs" />
<Compile Include="Src\CodeManipulation.cs" /> <Compile Include="Src\CodeManipulation.cs" />
@ -74,10 +75,10 @@
<Compile Include="Src\Completion\CSharpCompletionDataFactory.cs" /> <Compile Include="Src\Completion\CSharpCompletionDataFactory.cs" />
<Compile Include="Src\Completion\EntityCompletionData.cs" /> <Compile Include="Src\Completion\EntityCompletionData.cs" />
<Compile Include="Src\CSharpBracketSearcher.cs" /> <Compile Include="Src\CSharpBracketSearcher.cs" />
<Compile Include="Src\CSharpContextActionDoozer.cs" />
<Compile Include="Src\CSharpLanguageBinding.cs" /> <Compile Include="Src\CSharpLanguageBinding.cs" />
<Compile Include="Src\CSharpProjectBinding.cs" /> <Compile Include="Src\CSharpProjectBinding.cs" />
<Compile Include="Src\SDRefactoringContext.cs" /> <Compile Include="Src\Refactoring\CSharpContextActionDoozer.cs" />
<Compile Include="Src\Refactoring\SDRefactoringContext.cs" />
<Compile Include="Src\CSharpSemanticHighlighter.cs" /> <Compile Include="Src\CSharpSemanticHighlighter.cs" />
<Compile Include="Src\ExtensionMethods.cs" /> <Compile Include="Src\ExtensionMethods.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingStrategy.cs" /> <Compile Include="Src\FormattingStrategy\CSharpFormattingStrategy.cs" />
@ -134,6 +135,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Src\Completion" /> <Folder Include="Src\Completion" />
<Folder Include="Src\Refactoring" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project> </Project>

38
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpContextActionDoozer.cs → src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpContextActionDoozer.cs

@ -8,9 +8,10 @@ using System.Threading.Tasks;
using CSharpBinding.Parser; using CSharpBinding.Parser;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring; using ICSharpCode.SharpDevelop.Refactoring;
namespace CSharpBinding namespace CSharpBinding.Refactoring
{ {
using NR5ContextAction = ICSharpCode.NRefactory.CSharp.Refactoring.IContextAction; using NR5ContextAction = ICSharpCode.NRefactory.CSharp.Refactoring.IContextAction;
@ -57,28 +58,37 @@ namespace CSharpBinding
{ {
if (!string.Equals(Path.GetExtension(context.FileName), ".cs", StringComparison.OrdinalIgnoreCase)) if (!string.Equals(Path.GetExtension(context.FileName), ".cs", StringComparison.OrdinalIgnoreCase))
return Task.FromResult(false); return Task.FromResult(false);
ITextEditor editor = context.Editor;
// grab SelectionStart/SelectionLength while we're still on the main thread
int selectionStart = editor.SelectionStart;
int selectionLength = editor.SelectionLength;
return Task.Run( return Task.Run(
async delegate { async delegate {
// var parseInfo = (await context.GetParseInformationAsync().ConfigureAwait(false)) as CSharpFullParseInformation; CreateContextAction();
// if (parseInfo == null)
// return false;
lock (this) {
if (!contextActionCreated) {
contextActionCreated = true;
contextAction = (NR5ContextAction)addIn.CreateObject(className);
}
}
if (contextAction == null) if (contextAction == null)
return false; return false;
CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false); CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false);
//var refactoringContext = new SDRefactoringContext(context, resolver, cancellationToken); var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken);
return true; return contextAction.IsValid(refactoringContext);
}, cancellationToken); }, cancellationToken);
} }
public override void Execute(EditorContext context) void CreateContextAction()
{ {
throw new NotImplementedException(); lock (this) {
if (!contextActionCreated) {
contextActionCreated = true;
contextAction = (NR5ContextAction)addIn.CreateObject(className);
}
}
}
public override async Task ExecuteAsync(EditorContext context)
{
var resolver = await context.GetAstResolverAsync();
var refactoringContext = new SDRefactoringContext(context.Editor, resolver, context.CaretLocation);
CreateContextAction();
contextAction.Run(refactoringContext);
} }
} }
} }

158
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs

@ -0,0 +1,158 @@
// 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 System.Threading;
using CSharpBinding.Parser;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Refactoring;
namespace CSharpBinding.Refactoring
{
public class SDRefactoringContext : RefactoringContext
{
readonly ITextEditor editor;
readonly ITextSource textSource;
volatile IDocument document;
readonly CSharpAstResolver resolver;
int selectionStart, selectionLength;
CancellationToken cancellationToken;
public SDRefactoringContext(ITextSource textSource, CSharpAstResolver resolver, TextLocation location, int selectionStart, int selectionLength, CancellationToken cancellationToken)
{
this.textSource = textSource;
this.document = textSource as IDocument;
this.resolver = resolver;
this.selectionStart = selectionStart;
this.selectionLength = selectionLength;
this.cancellationToken = cancellationToken;
this.Unit = resolver.RootNode as CompilationUnit;
this.Compilation = resolver.Compilation;
this.Location = location;
}
public SDRefactoringContext(ITextEditor editor, CSharpAstResolver resolver, TextLocation location)
{
this.editor = editor;
this.textSource = editor.Document;
this.document = editor.Document;
this.resolver = resolver;
this.selectionStart = editor.SelectionStart;
this.selectionLength = editor.SelectionLength;
this.Unit = resolver.RootNode as CompilationUnit;
this.Compilation = resolver.Compilation;
this.Location = location;
}
public override bool Supports(Version version)
{
CSharpProject project = resolver.TypeResolveContext.Compilation.GetProject() as CSharpProject;
if (project == null)
return false;
return project.LanguageVersion >= version;
}
public override NodeOutputAction CreateNodeOutputAction(int offset, int removedChars, NodeOutput output)
{
return new SDScript.SDNodeOutputAction(document, offset, removedChars, output);
}
public override Script StartScript()
{
if (editor == null)
throw new InvalidOperationException("Cannot start a script in IsAvailable().");
return new SDScript(editor, this);
}
public override int SelectionStart {
get { return selectionStart; }
}
public override int SelectionLength {
get { return selectionLength; }
}
public override int SelectionEnd {
get {
return selectionStart + selectionLength;
}
}
public override string SelectedText {
get {
return textSource.GetText(selectionStart, selectionLength);
}
}
public override ResolveResult Resolve(AstNode expression)
{
lock (resolver)
return resolver.Resolve(expression, cancellationToken);
}
public override void ReplaceReferences(IMember member, MemberDeclaration replaceWidth)
{
throw new NotImplementedException();
}
public override bool IsSomethingSelected {
get {
return selectionLength > 0;
}
}
public override string GetText(int offset, int length)
{
return textSource.GetText(offset, length);
}
public override int GetOffset(TextLocation location)
{
if (document == null)
document = new ReadOnlyDocument(textSource);
return document.GetOffset(location);
}
public override TextLocation GetLocation(int offset)
{
if (document == null)
document = new ReadOnlyDocument(textSource);
return document.GetLocation(offset);
}
public override CSharpFormattingOptions FormattingOptions {
get {
return new CSharpFormattingOptions();
}
}
public override string EolMarker {
get {
if (document == null)
document = new ReadOnlyDocument(textSource);
return DocumentUtilitites.GetLineTerminator(document, 1);
}
}
public override AstType CreateShortType(IType fullType)
{
CSharpResolver csResolver;
lock (resolver) {
csResolver = resolver.GetResolverStateBefore(GetNode());
}
var builder = new TypeSystemAstBuilder(csResolver);
return builder.ConvertType(fullType);
}
}
}

83
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs

@ -0,0 +1,83 @@
// 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 System.Collections.Generic;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding.Refactoring
{
/// <summary>
/// Refactoring change script.
/// </summary>
sealed class SDScript : Script
{
readonly ITextEditor editor;
public SDScript(ITextEditor editor, SDRefactoringContext context) : base(context)
{
this.editor = editor;
}
public static void RunActions (IList<ICSharpCode.NRefactory.CSharp.Refactoring.Action> actions, Script script)
{
for (int i = 0; i < actions.Count; i++) {
actions [i].Perform (script);
var replaceChange = actions [i] as TextReplaceAction;
if (replaceChange == null)
continue;
for (int j = 0; j < actions.Count; j++) {
if (i == j)
continue;
var change = actions [j] as TextReplaceAction;
if (change == null)
continue;
if (replaceChange.Offset >= 0 && change.Offset >= 0) {
if (replaceChange.Offset < change.Offset) {
change.Offset -= replaceChange.RemovedChars;
if (!string.IsNullOrEmpty (replaceChange.InsertedText))
change.Offset += replaceChange.InsertedText.Length;
} else if (replaceChange.Offset < change.Offset + change.RemovedChars) {
change.RemovedChars = Math.Max (0, change.RemovedChars - replaceChange.RemovedChars);
change.Offset = replaceChange.Offset + (!string.IsNullOrEmpty (replaceChange.InsertedText) ? replaceChange.InsertedText.Length : 0);
}
}
}
}
}
public override void Dispose ()
{
using (editor.Document.OpenUndoGroup ()) {
RunActions (changes, this);
}
}
public override void InsertWithCursor(string operation, AstNode node, InsertPosition defaultPosition)
{
throw new NotImplementedException();
}
internal class SDNodeOutputAction : NodeOutputAction
{
IDocument doc;
public SDNodeOutputAction(IDocument doc, int offset, int removedChars, NodeOutput output) : base (offset, removedChars, output)
{
if (doc == null)
throw new ArgumentNullException ("doc");
if (output == null)
throw new ArgumentNullException ("output");
this.doc = doc;
}
public override void Perform (Script script)
{
doc.Replace (Offset, RemovedChars, NodeOutput.Text);
}
}
}
}

123
src/AddIns/BackendBindings/CSharpBinding/Project/Src/SDRefactoringContext.cs

@ -1,123 +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 System.Threading;
using CSharpBinding.Parser;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
namespace CSharpBinding
{
public class SDRefactoringContext : RefactoringContext
{
ITextEditor editor;
ICompilation compilation;
CancellationToken cancellationToken;
public SDRefactoringContext(ITextEditor editor, CancellationToken cancellationToken)
{
this.editor = editor;
this.cancellationToken = cancellationToken;
this.compilation = ParserService.GetCompilationForFile(editor.FileName);
}
public override bool Supports(Version version)
{
CSharpProject project = compilation.GetProject() as CSharpProject;
if (project == null)
return false;
return project.LanguageVersion >= version;
}
public override Script StartScript()
{
throw new NotImplementedException();
}
public override int SelectionStart {
get {
return editor.SelectionStart;
}
}
public override int SelectionLength {
get {
return editor.SelectionLength;
}
}
public override int SelectionEnd {
get {
return editor.SelectionStart + editor.SelectionLength;
}
}
public override string SelectedText {
get {
return editor.SelectedText;
}
}
public override ResolveResult Resolve(AstNode expression)
{
var parseInfo = ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
var resolver = new CSharpAstResolver(compilation, parseInfo.CompilationUnit, parseInfo.ParsedFile);
return resolver.Resolve(expression, cancellationToken);
}
public override void ReplaceReferences(IMember member, MemberDeclaration replaceWidth)
{
throw new NotImplementedException();
}
public override bool IsSomethingSelected {
get {
return editor.SelectionLength > 0;
}
}
public override string GetText(int offset, int length)
{
return editor.Document.GetText(offset, length);
}
public override int GetOffset(TextLocation location)
{
return editor.Document.GetOffset(location);
}
public override TextLocation GetLocation(int offset)
{
return editor.Document.GetLocation(offset);
}
public override CSharpFormattingOptions FormattingOptions {
get {
return new CSharpFormattingOptions();
}
}
public override string EolMarker {
get {
return DocumentUtilitites.GetLineTerminator(editor.Document, 1);
}
}
public override AstType CreateShortType(IType fullType)
{
var parseInfo = ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
var parsedFile = parseInfo.ParsedFile;
var csResolver = parsedFile.GetResolver(compilation, editor.Caret.Location);
var builder = new TypeSystemAstBuilder(csResolver);
return builder.ConvertType(fullType);
}
}
}

2
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextAction.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// <remarks><inheritdoc cref="IContextActionsProvider.GetAvailableActionsAsync"/></remarks> /// <remarks><inheritdoc cref="IContextActionsProvider.GetAvailableActionsAsync"/></remarks>
public abstract Task<bool> IsAvailableAsync(EditorContext context, CancellationToken cancellationToken); public abstract Task<bool> IsAvailableAsync(EditorContext context, CancellationToken cancellationToken);
public abstract void Execute(EditorContext context); public abstract Task ExecuteAsync(EditorContext context);
async Task<IContextAction[]> IContextActionsProvider.GetAvailableActionsAsync(EditorContext context, CancellationToken cancellationToken) async Task<IContextAction[]> IContextActionsProvider.GetAvailableActionsAsync(EditorContext context, CancellationToken cancellationToken)
{ {

2
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionViewModel.cs

@ -86,7 +86,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public void Execute(object parameter) public void Execute(object parameter)
{ {
this.action.Execute(context); this.action.ExecuteAsync(context).FireAndForget();
} }
public bool CanExecute(object parameter) public bool CanExecute(object parameter)

7
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/EditorContext.cs

@ -59,6 +59,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring
get { return caretOffset; } get { return caretOffset; }
} }
/// <summary>
/// Gets caret location, at the time when this editor context was created.
/// </summary>
public TextLocation CaretLocation {
get { return caretLocation; }
}
Task<ParseInformation> parseInformation; Task<ParseInformation> parseInformation;
Task<ICompilation> compilation; Task<ICompilation> compilation;

3
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextAction.cs

@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
namespace ICSharpCode.SharpDevelop.Refactoring namespace ICSharpCode.SharpDevelop.Refactoring
@ -18,6 +19,6 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// <summary> /// <summary>
/// Executes this action. Called when this action is selected from the context actions popup. /// Executes this action. Called when this action is selected from the context actions popup.
/// </summary> /// </summary>
void Execute(EditorContext context); Task ExecuteAsync(EditorContext context);
} }
} }

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

@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Threading.Tasks;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
@ -22,9 +23,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring
this.DisplayName = ambience.ConvertEntity(entity); this.DisplayName = ambience.ConvertEntity(entity);
} }
public void Execute(EditorContext context) public Task ExecuteAsync(EditorContext context)
{ {
NavigationService.NavigateTo(this.Entity); NavigationService.NavigateTo(this.Entity);
return Task.FromResult<object>(null);
} }
} }
} }

Loading…
Cancel
Save