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

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

@ -66,6 +66,7 @@ @@ -66,6 +66,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\Refactoring\SDScript.cs" />
<EmbeddedResource Include="Resources\BuildOptions.xfrm" />
<EmbeddedResource Include="Resources\MyNamespaceSupportForCSharp.cs" />
<Compile Include="Src\CodeManipulation.cs" />
@ -74,10 +75,10 @@ @@ -74,10 +75,10 @@
<Compile Include="Src\Completion\CSharpCompletionDataFactory.cs" />
<Compile Include="Src\Completion\EntityCompletionData.cs" />
<Compile Include="Src\CSharpBracketSearcher.cs" />
<Compile Include="Src\CSharpContextActionDoozer.cs" />
<Compile Include="Src\CSharpLanguageBinding.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\ExtensionMethods.cs" />
<Compile Include="Src\FormattingStrategy\CSharpFormattingStrategy.cs" />
@ -134,6 +135,7 @@ @@ -134,6 +135,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Src\Completion" />
<Folder Include="Src\Refactoring" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</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; @@ -8,9 +8,10 @@ using System.Threading.Tasks;
using CSharpBinding.Parser;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
namespace CSharpBinding
namespace CSharpBinding.Refactoring
{
using NR5ContextAction = ICSharpCode.NRefactory.CSharp.Refactoring.IContextAction;
@ -57,28 +58,37 @@ namespace CSharpBinding @@ -57,28 +58,37 @@ namespace CSharpBinding
{
if (!string.Equals(Path.GetExtension(context.FileName), ".cs", StringComparison.OrdinalIgnoreCase))
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(
async delegate {
// var parseInfo = (await context.GetParseInformationAsync().ConfigureAwait(false)) as CSharpFullParseInformation;
// if (parseInfo == null)
// return false;
lock (this) {
if (!contextActionCreated) {
contextActionCreated = true;
contextAction = (NR5ContextAction)addIn.CreateObject(className);
}
}
CreateContextAction();
if (contextAction == null)
return false;
CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false);
//var refactoringContext = new SDRefactoringContext(context, resolver, cancellationToken);
return true;
var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken);
return contextAction.IsValid(refactoringContext);
}, 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 @@ @@ -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 @@ @@ -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 @@ @@ -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 @@ -30,7 +30,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// <remarks><inheritdoc cref="IContextActionsProvider.GetAvailableActionsAsync"/></remarks>
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)
{

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

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

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

@ -59,6 +59,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -59,6 +59,13 @@ namespace ICSharpCode.SharpDevelop.Refactoring
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<ICompilation> compilation;

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

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

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

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

Loading…
Cancel
Save