Browse Source

Implemented support for issue providers and quick fixes.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
541497a978
  1. 107
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 5
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  3. 12
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
  4. 78
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeActionProviderDoozer.cs
  5. 62
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpContextActionWrapper.cs
  6. 116
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs
  7. 4
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs
  8. 2
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  9. 5
      src/Main/Base/Project/Src/Editor/ITextMarker.cs
  10. 4
      src/Main/Base/Project/Src/Refactoring/ContextAction.cs
  11. 12
      src/Main/Base/Project/Src/Refactoring/IContextActionProvider.cs

107
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.Refactoring.CSharpContextActionDoozer"/> <Doozer name="CSharpCodeActionProvider" class="CSharpBinding.Refactoring.CSharpCodeActionProviderDoozer"/>
</Import> </Import>
<Import assembly = ":ICSharpCode.SharpDevelop"/> <Import assembly = ":ICSharpCode.SharpDevelop"/>
<Import assembly = ":ICSharpCode.NRefactory.CSharp"/> <Import assembly = ":ICSharpCode.NRefactory.CSharp"/>
@ -116,7 +116,7 @@
class = "CSharpBinding.CSharpProjectBinding" /> class = "CSharpBinding.CSharpProjectBinding" />
</Path> </Path>
<Path path = "/SharpDevelop/ViewContent/TextEditor/C#/Inspectors"> <Path path = "/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders">
<Class id = "ConditionalToNullCoalescingInspector" <Class id = "ConditionalToNullCoalescingInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConditionalToNullCoalescingInspector" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConditionalToNullCoalescingInspector" />
<Class id = "NotImplementedExceptionInspector" <Class id = "NotImplementedExceptionInspector"
@ -138,56 +138,57 @@
</Path> </Path>
<Path path = "/SharpDevelop/ViewContent/TextEditor/C#/ContextActions"> <Path path = "/SharpDevelop/ViewContent/TextEditor/C#/ContextActions">
<!-- TODO: translate --> <!-- In this path, you can add SD context action providers using <Class>,
<CSharpContextAction id = "AddAnotherAccessor" or you can add NR5 code action providers using <CSharpCodeActionProvider> -->
class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddAnotherAccessor" /> <CSharpCodeActionProvider id = "AddAnotherAccessor"
<CSharpContextAction id = "CheckIfParameterIsNull" class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddAnotherAccessor" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CheckIfParameterIsNull" /> <CSharpCodeActionProvider id = "CheckIfParameterIsNull"
<CSharpContextAction id = "ConvertDecToHex" class = "ICSharpCode.NRefactory.CSharp.Refactoring.CheckIfParameterIsNull" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertDecToHex" /> <CSharpCodeActionProvider id = "ConvertDecToHex"
<CSharpContextAction id = "ConvertHexToDec" class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertDecToHex" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertHexToDec" /> <CSharpCodeActionProvider id = "ConvertHexToDec"
<CSharpContextAction id = "ConvertForeachToFor" class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertHexToDec" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertForeachToFor" /> <CSharpCodeActionProvider id = "ConvertForeachToFor"
<CSharpContextAction id = "CreateBackingStore" class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertForeachToFor" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateBackingStore" /> <CSharpCodeActionProvider id = "CreateBackingStore"
<CSharpContextAction id = "CreateEventInvocator" class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateBackingStore" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateEventInvocator" /> <CSharpCodeActionProvider id = "CreateEventInvocator"
<CSharpContextAction id = "CreateField" class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateEventInvocator" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateField" /> <CSharpCodeActionProvider id = "CreateField"
<CSharpContextAction id = "CreateLocalVariable" class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateField" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateLocalVariable" /> <CSharpCodeActionProvider id = "CreateLocalVariable"
<CSharpContextAction id = "CreateProperty" class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateLocalVariable" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateProperty" /> <CSharpCodeActionProvider id = "CreateProperty"
<CSharpContextAction id = "FlipOperatorArguments" class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateProperty" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.FlipOperatorArguments" /> <CSharpCodeActionProvider id = "FlipOperatorArguments"
<CSharpContextAction id = "GenerateGetter" class = "ICSharpCode.NRefactory.CSharp.Refactoring.FlipOperatorArguments" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateGetter" /> <CSharpCodeActionProvider id = "GenerateGetter"
<CSharpContextAction id = "GenerateProperty" class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateGetter" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateProperty" /> <CSharpCodeActionProvider id = "GenerateProperty"
<CSharpContextAction id = "GenerateSwitchLabels" class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateProperty" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateSwitchLabels" /> <CSharpCodeActionProvider id = "GenerateSwitchLabels"
<CSharpContextAction id = "InsertAnonymousMethodSignature" class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateSwitchLabels" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.InsertAnonymousMethodSignature" /> <CSharpCodeActionProvider id = "InsertAnonymousMethodSignature"
<CSharpContextAction id = "IntroduceFormatItem" class = "ICSharpCode.NRefactory.CSharp.Refactoring.InsertAnonymousMethodSignature" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.IntroduceFormatItem" /> <CSharpCodeActionProvider id = "IntroduceFormatItem"
<CSharpContextAction id = "InvertIf" class = "ICSharpCode.NRefactory.CSharp.Refactoring.IntroduceFormatItem" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvertIf" /> <CSharpCodeActionProvider id = "InvertIf"
<CSharpContextAction id = "RemoveBackingStore" class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvertIf" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBackingStore" /> <CSharpCodeActionProvider id = "RemoveBackingStore"
<CSharpContextAction id = "RemoveBraces" class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBackingStore" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBraces" /> <CSharpCodeActionProvider id = "RemoveBraces"
<CSharpContextAction id = "RemoveRegion" class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBraces" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRegion" /> <CSharpCodeActionProvider id = "RemoveRegion"
<CSharpContextAction id = "ReplaceEmptyString" class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRegion" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceEmptyString" /> <CSharpCodeActionProvider id = "ReplaceEmptyString"
<CSharpContextAction id = "SplitDeclarationAndAssignment" class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceEmptyString" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitDeclarationAndAssignment" /> <CSharpCodeActionProvider id = "SplitDeclarationAndAssignment"
<CSharpContextAction id = "SplitString" class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitDeclarationAndAssignment" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitString" /> <CSharpCodeActionProvider id = "SplitString"
<CSharpContextAction id = "UseExplicitType" class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitString" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseExplicitType" /> <CSharpCodeActionProvider id = "UseExplicitType"
<CSharpContextAction id = "UseVarKeyword" class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseExplicitType" />
class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeyword" /> <CSharpCodeActionProvider id = "UseVarKeyword"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeyword" />
</Path> </Path>
</AddIn> </AddIn>

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

@ -66,7 +66,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\AssemblyInfo.cs" /> <Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\Refactoring\InspectionManager.cs" /> <Compile Include="Src\Refactoring\CSharpContextActionWrapper.cs" />
<Compile Include="Src\Refactoring\IssueManager.cs" />
<Compile Include="Src\Refactoring\SDScript.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" />
@ -78,7 +79,7 @@
<Compile Include="Src\CSharpBracketSearcher.cs" /> <Compile Include="Src\CSharpBracketSearcher.cs" />
<Compile Include="Src\CSharpLanguageBinding.cs" /> <Compile Include="Src\CSharpLanguageBinding.cs" />
<Compile Include="Src\CSharpProjectBinding.cs" /> <Compile Include="Src\CSharpProjectBinding.cs" />
<Compile Include="Src\Refactoring\CSharpContextActionDoozer.cs" /> <Compile Include="Src\Refactoring\CSharpCodeActionProviderDoozer.cs" />
<Compile Include="Src\Refactoring\SDRefactoringContext.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" />

12
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs

@ -33,7 +33,7 @@ namespace CSharpBinding
ITextEditor editor; ITextEditor editor;
CSharpSemanticHighlighter semanticHighlighter; CSharpSemanticHighlighter semanticHighlighter;
//InspectionManager inspectionManager; IssueManager inspectionManager;
IList<IContextActionProvider> contextActionProviders; IList<IContextActionProvider> contextActionProviders;
public override void Attach(ITextEditor editor) public override void Attach(ITextEditor editor)
@ -45,7 +45,7 @@ namespace CSharpBinding
semanticHighlighter = new CSharpSemanticHighlighter(editor, highlighter); semanticHighlighter = new CSharpSemanticHighlighter(editor, highlighter);
highlighter.AddAdditionalHighlighter(semanticHighlighter); highlighter.AddAdditionalHighlighter(semanticHighlighter);
} }
//inspectionManager = new InspectionManager(editor); inspectionManager = new IssueManager(editor);
//codeManipulation = new CodeManipulation(editor); //codeManipulation = new CodeManipulation(editor);
if (!editor.ContextActionProviders.IsReadOnly) { if (!editor.ContextActionProviders.IsReadOnly) {
@ -63,10 +63,10 @@ namespace CSharpBinding
semanticHighlighter.Dispose(); semanticHighlighter.Dispose();
semanticHighlighter = null; semanticHighlighter = null;
} }
// if (inspectionManager != null) { if (inspectionManager != null) {
// inspectionManager.Dispose(); inspectionManager.Dispose();
// inspectionManager = null; inspectionManager = null;
// } }
if (contextActionProviders != null) { if (contextActionProviders != null) {
editor.ContextActionProviders.RemoveWhere(contextActionProviders.Contains); editor.ContextActionProviders.RemoveWhere(contextActionProviders.Contains);
} }

78
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpContextActionDoozer.cs → src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpCodeActionProviderDoozer.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.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@ -20,7 +21,7 @@ namespace CSharpBinding.Refactoring
/// Doozer for C# context actions. /// Doozer for C# context actions.
/// Expects a 'class' referencing an NR5 context action and provides an SD IContextActionsProvider. /// Expects a 'class' referencing an NR5 context action and provides an SD IContextActionsProvider.
/// </summary> /// </summary>
public class CSharpContextActionDoozer : IDoozer public class CSharpCodeActionProviderDoozer : IDoozer
{ {
public bool HandleConditions { public bool HandleConditions {
get { return false; } get { return false; }
@ -70,6 +71,14 @@ namespace CSharpBinding.Refactoring
get { return type.FullName; } get { return type.FullName; }
} }
public string DisplayName {
get { return attribute.Title; }
}
public string Category {
get { return attribute.Category; }
}
public bool AllowHiding { public bool AllowHiding {
get { return true; } get { return true; }
} }
@ -88,62 +97,25 @@ namespace CSharpBinding.Refactoring
return new IContextAction[0]; return new IContextAction[0];
CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false); CSharpAstResolver resolver = await context.GetAstResolverAsync().ConfigureAwait(false);
var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken); var refactoringContext = new SDRefactoringContext(context.TextSource, resolver, context.CaretLocation, selectionStart, selectionLength, cancellationToken);
return codeActionProvider.GetActions(refactoringContext) return codeActionProvider.GetActions(refactoringContext).Select(Wrap).ToArray();
.Select((action, index) => new CSharpContextActionWrapper(this, action, index)).ToArray();
}, cancellationToken); }, cancellationToken);
} }
internal CodeAction GetCodeAction(RefactoringContext refactoringContext, int index, string description) IContextAction Wrap(CodeAction actionToWrap, int index)
{ {
if (!CreateCodeActionProvider()) // Take care not to capture 'actionToWrap' in the lambda
return null; string description = actionToWrap.Description;
var actions = codeActionProvider.GetActions(refactoringContext).ToList(); return new CSharpContextActionWrapper(
if (index < actions.Count) { this, actionToWrap,
var action = actions[index]; context => {
if (action.Description == description) var actions = codeActionProvider.GetActions(context).ToList();
return action; if (index < actions.Count) {
} var action = actions[index];
return null; if (action.Description == description)
} return action;
} }
return null;
sealed class CSharpContextActionWrapper : IContextAction });
{
readonly CSharpContextActionProviderWrapper provider;
readonly int index;
readonly string description;
public CSharpContextActionWrapper(CSharpContextActionProviderWrapper provider, CodeAction codeAction, int index)
{
if (provider == null)
throw new ArgumentNullException("provider");
if (codeAction == null)
throw new ArgumentNullException("codeAction");
this.provider = provider;
this.description = codeAction.Description;
this.index = index;
// Don't maintain a reference to 'action', it indirectly references the compilation etc.
}
public IContextActionProvider Provider {
get { return provider; }
}
public string DisplayName {
get { return description; }
}
public void Execute(EditorRefactoringContext context)
{
AnalyticsMonitorService.TrackFeature(provider.ID);
var resolver = context.GetAstResolverAsync().Result;
var refactoringContext = new SDRefactoringContext(context.Editor, resolver, context.CaretLocation);
var action = provider.GetCodeAction(refactoringContext, index, description);
if (action != null) {
using (var script = refactoringContext.StartScript()) {
action.Run(script);
}
}
} }
} }
} }

62
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/CSharpContextActionWrapper.cs

@ -0,0 +1,62 @@
// 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 System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CSharpBinding.Parser;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
namespace CSharpBinding.Refactoring
{
sealed class CSharpContextActionWrapper : IContextAction
{
readonly IContextActionProvider provider;
readonly string description;
readonly Func<SDRefactoringContext, CodeAction> getUpdatedCodeAction;
public CSharpContextActionWrapper(IContextActionProvider provider, CodeAction codeAction,
Func<SDRefactoringContext, CodeAction> getUpdatedCodeAction)
{
if (provider == null)
throw new ArgumentNullException("provider");
if (codeAction == null)
throw new ArgumentNullException("codeAction");
if (getUpdatedCodeAction == null)
throw new ArgumentNullException("getUpdatedCodeAction");
this.provider = provider;
this.description = codeAction.Description;
this.getUpdatedCodeAction = getUpdatedCodeAction;
// Don't maintain a reference to 'action', it indirectly references the compilation etc.
}
public IContextActionProvider Provider {
get { return provider; }
}
public string DisplayName {
get { return description; }
}
public void Execute(EditorRefactoringContext context)
{
AnalyticsMonitorService.TrackFeature(provider.ID);
var resolver = context.GetAstResolverAsync().Result;
var refactoringContext = new SDRefactoringContext(context.Editor, resolver, context.CaretLocation);
var action = getUpdatedCodeAction(refactoringContext);
if (action != null) {
using (var script = refactoringContext.StartScript()) {
action.Run(script);
}
}
}
}
}

116
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InspectionManager.cs → src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Media; using System.Windows.Media;
@ -15,29 +16,31 @@ using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Refactoring;
namespace CSharpBinding.Refactoring namespace CSharpBinding.Refactoring
{ {
/*
/// <summary> /// <summary>
/// Performs code analysis in the background and creates text markers to show warnings. /// Performs code analysis in the background and creates text markers to show warnings.
/// </summary> /// </summary>
public class InspectionManager : IDisposable public class IssueManager : IDisposable, IContextActionProvider
{ {
static readonly Lazy<IList<IInspector>> inspectors = new Lazy<IList<IInspector>>( static readonly Lazy<IList<ICodeIssueProvider>> issueProviders = new Lazy<IList<ICodeIssueProvider>>(
() => AddInTree.BuildItems<IInspector>("/SharpDevelop/ViewContent/TextEditor/C#/Inspectors", null, false)); () => AddInTree.BuildItems<ICodeIssueProvider>("/SharpDevelop/ViewContent/TextEditor/C#/IssueProviders", null, false));
readonly ITextEditor editor; readonly ITextEditor editor;
readonly ITextMarkerService markerService; readonly ITextMarkerService markerService;
public InspectionManager(ITextEditor editor) public IssueManager(ITextEditor editor)
{ {
this.editor = editor; this.editor = editor;
this.markerService = editor.GetService(typeof(ITextMarkerService)) as ITextMarkerService; this.markerService = editor.GetService(typeof(ITextMarkerService)) as ITextMarkerService;
ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished; ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished;
editor.ContextActionProviders.Add(this);
} }
public void Dispose() public void Dispose()
{ {
editor.ContextActionProviders.Remove(this);
ParserService.ParserUpdateStepFinished -= ParserService_ParserUpdateStepFinished; ParserService.ParserUpdateStepFinished -= ParserService_ParserUpdateStepFinished;
if (cancellationTokenSource != null) if (cancellationTokenSource != null)
cancellationTokenSource.Cancel(); cancellationTokenSource.Cancel();
@ -46,31 +49,62 @@ namespace CSharpBinding.Refactoring
sealed class InspectionTag sealed class InspectionTag
{ {
public readonly IInspector Inspector; readonly IssueManager manager;
public readonly string Title; public readonly ICodeIssueProvider Provider;
public readonly ITextSourceVersion InspectedVersion;
public readonly string Description;
public readonly int StartOffset; public readonly int StartOffset;
public readonly int EndOffset; public readonly int EndOffset;
public readonly bool CanFix; public readonly IReadOnlyList<IContextAction> Actions;
public InspectionTag(IInspector inspector, string title, int startOffset, int endOffset, bool canFix) public InspectionTag(IssueManager manager, ICodeIssueProvider provider, ITextSourceVersion inspectedVersion, string description, int startOffset, int endOffset, IEnumerable<CodeAction> actions)
{ {
this.Inspector = inspector; this.manager = manager;
this.Title = title; this.Provider = provider;
this.InspectedVersion = inspectedVersion;
this.Description = description;
this.StartOffset = startOffset; this.StartOffset = startOffset;
this.EndOffset = endOffset; this.EndOffset = endOffset;
this.CanFix = canFix;
this.Actions = actions.Select(Wrap).ToList();
}
IContextAction Wrap(CodeAction actionToWrap, int index)
{
// Take care not to capture 'actionToWrap' in the lambda
string actionDescription = actionToWrap.Description;
return new CSharpContextActionWrapper(
manager, actionToWrap,
context => {
// Look up the new issue position
int newStart = InspectedVersion.MoveOffsetTo(context.Version, StartOffset, AnchorMovementType.Default);
int newEnd = InspectedVersion.MoveOffsetTo(context.Version, EndOffset, AnchorMovementType.Default);
// If the length changed, don't bother looking up the issue again
if (newEnd - newStart != EndOffset - StartOffset)
return null;
// Now rediscover this issue in the new context
var issue = this.Provider.GetIssues(context).FirstOrDefault(
i => context.GetOffset(i.Start) == newStart && context.GetOffset(i.End) == newEnd && i.Desription == this.Description);
if (issue == null)
return null;
// Now look up the action within that issue:
if (issue.Action != null && issue.Action.Description == actionDescription)
return issue.Action;
else
return null;
});
} }
ITextMarker marker; ITextMarker marker;
public void CreateMarker(ITextSourceVersion inspectedVersion, IDocument document, ITextMarkerService markerService) public void CreateMarker(IDocument document, ITextMarkerService markerService)
{ {
int startOffset = inspectedVersion.MoveOffsetTo(document.Version, this.StartOffset, AnchorMovementType.Default); int startOffset = InspectedVersion.MoveOffsetTo(document.Version, this.StartOffset, AnchorMovementType.Default);
int endOffset = inspectedVersion.MoveOffsetTo(document.Version, this.EndOffset, AnchorMovementType.Default); int endOffset = InspectedVersion.MoveOffsetTo(document.Version, this.EndOffset, AnchorMovementType.Default);
if (startOffset >= endOffset) if (startOffset >= endOffset)
return; return;
marker = markerService.Create(startOffset, endOffset - startOffset); marker = markerService.Create(startOffset, endOffset - startOffset);
marker.ToolTip = this.Title; marker.ToolTip = this.Description;
marker.MarkerType = TextMarkerType.SquigglyUnderline; marker.MarkerType = TextMarkerType.SquigglyUnderline;
marker.MarkerColor = Colors.Blue; marker.MarkerColor = Colors.Blue;
marker.Tag = this; marker.Tag = this;
@ -129,14 +163,16 @@ namespace CSharpBinding.Refactoring
var compilation = ParserService.GetCompilationForFile(parseInfo.FileName); var compilation = ParserService.GetCompilationForFile(parseInfo.FileName);
var resolver = parseInfo.GetResolver(compilation); var resolver = parseInfo.GetResolver(compilation);
var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken); var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken);
foreach (var inspector in inspectors.Value) { foreach (var issueProvider in issueProviders.Value) {
foreach (var issue in inspector.Run(context)) { foreach (var issue in issueProvider.GetIssues(context)) {
results.Add(new InspectionTag( results.Add(new InspectionTag(
inspector, this,
issue.Title, issueProvider,
textSource.Version,
issue.Desription,
context.GetOffset(issue.Start), context.GetOffset(issue.Start),
context.GetOffset(issue.End), context.GetOffset(issue.End),
issue.Fix != null)); issue.Action != null ? new [] { issue.Action } : new CodeAction[0]));
} }
} }
}, cancellationToken); }, cancellationToken);
@ -146,13 +182,47 @@ namespace CSharpBinding.Refactoring
analyzedVersion = textSource.Version; analyzedVersion = textSource.Version;
Clear(); Clear();
foreach (var newResult in results) { foreach (var newResult in results) {
newResult.CreateMarker(textSource.Version, editor.Document, markerService); newResult.CreateMarker(editor.Document, markerService);
} }
existingResults = results; existingResults = results;
} }
cancellationTokenSource.Dispose(); cancellationTokenSource.Dispose();
cancellationTokenSource = null; cancellationTokenSource = null;
} }
#region IContextActionProvider implementation
string IContextActionProvider.ID {
get { return "C# IssueManager"; }
}
string IContextActionProvider.DisplayName {
get { return "C# IssueManager"; }
}
string IContextActionProvider.Category {
get { return string.Empty; }
}
bool IContextActionProvider.AllowHiding {
get { return false; }
}
bool IContextActionProvider.IsVisible {
get { return true; }
set { }
}
Task<IContextAction[]> IContextActionProvider.GetAvailableActionsAsync(EditorRefactoringContext context, CancellationToken cancellationToken)
{
List<IContextAction> result = new List<IContextAction>();
if (existingResults != null) {
var markers = markerService.GetMarkersAtOffset(context.CaretOffset);
foreach (var tag in markers.Select(m => m.Tag).OfType<InspectionTag>()) {
result.AddRange(tag.Actions);
}
}
return Task.FromResult(result.ToArray());
}
#endregion
} }
*/
} }

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

@ -102,6 +102,10 @@ namespace CSharpBinding.Refactoring
return textSource.GetText(segment); return textSource.GetText(segment);
} }
public ITextSourceVersion Version {
get { return textSource.Version; }
}
public override IDocumentLine GetLineByOffset(int offset) public override IDocumentLine GetLineByOffset(int offset)
{ {
if (document == null) if (document == null)

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

@ -355,7 +355,7 @@
<Compile Include="Src\Refactoring\ContextAction.cs" /> <Compile Include="Src\Refactoring\ContextAction.cs" />
<Compile Include="Src\Refactoring\EditorRefactoringContext.cs" /> <Compile Include="Src\Refactoring\EditorRefactoringContext.cs" />
<Compile Include="Src\Refactoring\IContextAction.cs" /> <Compile Include="Src\Refactoring\IContextAction.cs" />
<Compile Include="Src\Refactoring\IContextActionsProvider.cs" /> <Compile Include="Src\Refactoring\IContextActionProvider.cs" />
<Compile Include="Src\Services\AmbienceService\DefaultAmbience.cs" /> <Compile Include="Src\Services\AmbienceService\DefaultAmbience.cs" />
<Compile Include="Src\Services\ClassBrowserIcons\ImageSourceImage.cs" /> <Compile Include="Src\Services\ClassBrowserIcons\ImageSourceImage.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" /> <Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" />

5
src/Main/Base/Project/Src/Editor/ITextMarker.cs

@ -107,5 +107,10 @@ namespace ICSharpCode.SharpDevelop.Editor
/// Removes all text markers that match the condition. /// Removes all text markers that match the condition.
/// </summary> /// </summary>
void RemoveAll(Predicate<ITextMarker> predicate); void RemoveAll(Predicate<ITextMarker> predicate);
/// <summary>
/// Finds all text markers at the specified offset.
/// </summary>
IEnumerable<ITextMarker> GetMarkersAtOffset(int offset);
} }
} }

4
src/Main/Base/Project/Src/Refactoring/ContextAction.cs

@ -22,6 +22,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public abstract string DisplayName { get; } public abstract string DisplayName { get; }
public virtual string Category {
get { return string.Empty; }
}
public bool IsVisible { get; set; } public bool IsVisible { get; set; }
public virtual bool AllowHiding { public virtual bool AllowHiding {

12
src/Main/Base/Project/Src/Refactoring/IContextActionsProvider.cs → src/Main/Base/Project/Src/Refactoring/IContextActionProvider.cs

@ -19,6 +19,18 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// </summary> /// </summary>
string ID { get; } string ID { get; }
/// <summary>
/// Gets the title for this context action provider - should be similar to the DisplayName
/// of the generated context actions. Displayed in the options dialog for disabling providers.
/// </summary>
string DisplayName { get; }
/// <summary>
/// Gets a category for this context action provider - used to group context actions
/// in the options dialog.
/// </summary>
string Category { get; }
/// <summary> /// <summary>
/// Gets actions available for current line of the editor. /// Gets actions available for current line of the editor.
/// </summary> /// </summary>
Loading…
Cancel
Save