Browse Source

Add support for inspectors.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
5802f18c4a
  1. 21
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  3. 7
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpLanguageBinding.cs
  4. 156
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InspectionManager.cs
  5. 3
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs
  6. 14
      src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs

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

@ -116,6 +116,27 @@ @@ -116,6 +116,27 @@
class = "CSharpBinding.CSharpProjectBinding" />
</Path>
<Path path = "/SharpDevelop/ViewContent/TextEditor/C#/Inspectors">
<Class id = "ConditionalToNullCoalescingInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConditionalToNullCoalescingInspector" />
<Class id = "NotImplementedExceptionInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.NotImplementedExceptionInspector" />
<Class id = "RedundantInternalInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantInternalInspector" />
<Class id = "RedundantNamespaceUsageInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantNamespaceUsageInspector" />
<Class id = "RedundantPrivateInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantPrivateInspector" />
<Class id = "RedundantThisInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantThisInspector" />
<Class id = "RedundantUsingInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.RedundantUsingInspector" />
<Class id = "StringIsNullOrEmptyInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.StringIsNullOrEmptyInspector" />
<Class id = "UseVarKeywordInspector"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeywordInspector" />
</Path>
<Path path = "/SharpDevelop/ViewContent/AvalonEdit/ContextActions">
<!-- TODO: translate -->
<CSharpContextAction id = "AddAnotherAccessor"

1
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\InspectionManager.cs" />
<Compile Include="Src\Refactoring\SDScript.cs" />
<EmbeddedResource Include="Resources\BuildOptions.xfrm" />
<EmbeddedResource Include="Resources\MyNamespaceSupportForCSharp.cs" />

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

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.ComponentModel.Design;
using CSharpBinding.FormattingStrategy;
using CSharpBinding.Refactoring;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
@ -29,6 +30,7 @@ namespace CSharpBinding @@ -29,6 +30,7 @@ namespace CSharpBinding
ITextEditor editor;
CSharpSemanticHighlighter semanticHighlighter;
InspectionManager inspectionManager;
public override void Attach(ITextEditor editor)
{
@ -39,6 +41,7 @@ namespace CSharpBinding @@ -39,6 +41,7 @@ namespace CSharpBinding
semanticHighlighter = new CSharpSemanticHighlighter(editor, highlighter);
highlighter.AddAdditionalHighlighter(semanticHighlighter);
}
inspectionManager = new InspectionManager(editor);
//codeManipulation = new CodeManipulation(editor);
}
@ -51,6 +54,10 @@ namespace CSharpBinding @@ -51,6 +54,10 @@ namespace CSharpBinding
semanticHighlighter.Dispose();
semanticHighlighter = null;
}
if (inspectionManager != null) {
inspectionManager.Dispose();
inspectionManager = null;
}
this.editor = null;
base.Detach();
}

156
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InspectionManager.cs

@ -0,0 +1,156 @@ @@ -0,0 +1,156 @@
// 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.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Media;
using CSharpBinding.Parser;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
namespace CSharpBinding.Refactoring
{
/// <summary>
/// Performs code analysis in the background and creates text markers to show warnings.
/// </summary>
public class InspectionManager : IDisposable
{
static readonly Lazy<IList<IInspector>> inspectors = new Lazy<IList<IInspector>>(
() => AddInTree.BuildItems<IInspector>("/SharpDevelop/ViewContent/TextEditor/C#/Inspectors", null, false));
readonly ITextEditor editor;
readonly ITextMarkerService markerService;
public InspectionManager(ITextEditor editor)
{
this.editor = editor;
this.markerService = editor.GetService(typeof(ITextMarkerService)) as ITextMarkerService;
ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished;
}
public void Dispose()
{
ParserService.ParserUpdateStepFinished -= ParserService_ParserUpdateStepFinished;
if (cancellationTokenSource != null)
cancellationTokenSource.Cancel();
Clear();
}
sealed class InspectionTag
{
public readonly IInspector Inspector;
public readonly string Title;
public readonly int StartOffset;
public readonly int EndOffset;
public readonly bool CanFix;
public InspectionTag(IInspector inspector, string title, int startOffset, int endOffset, bool canFix)
{
this.Inspector = inspector;
this.Title = title;
this.StartOffset = startOffset;
this.EndOffset = endOffset;
this.CanFix = canFix;
}
ITextMarker marker;
public void CreateMarker(ITextSourceVersion inspectedVersion, IDocument document, ITextMarkerService markerService)
{
int startOffset = inspectedVersion.MoveOffsetTo(document.Version, this.StartOffset, AnchorMovementType.Default);
int endOffset = inspectedVersion.MoveOffsetTo(document.Version, this.EndOffset, AnchorMovementType.Default);
if (startOffset >= endOffset)
return;
marker = markerService.Create(startOffset, endOffset - startOffset);
marker.ToolTip = this.Title;
marker.MarkerType = TextMarkerType.SquigglyUnderline;
marker.MarkerColor = Colors.Blue;
marker.Tag = this;
}
public void RemoveMarker()
{
if (marker != null) {
marker.Delete();
marker = null;
}
}
}
CancellationTokenSource cancellationTokenSource;
ITextSourceVersion analyzedVersion;
List<InspectionTag> existingResults;
void Clear()
{
if (existingResults != null) {
foreach (var oldResult in existingResults) {
oldResult.RemoveMarker();
}
existingResults = null;
}
analyzedVersion = null;
}
void ParserService_ParserUpdateStepFinished(object sender, ParserUpdateStepEventArgs e)
{
var parseInfo = e.ParseInformation as CSharpFullParseInformation;
ITextSourceVersion currentVersion = editor.Document.Version;
ITextSourceVersion parsedVersion = e.Content.Version;
if (parseInfo != null && parsedVersion != null && currentVersion != null && parsedVersion.BelongsToSameDocumentAs(currentVersion)) {
if (analyzedVersion != null && analyzedVersion.CompareAge(parsedVersion) == 0) {
// don't analyze the same version twice
return;
}
RunAnalysis(e.Content, parseInfo);
}
}
async void RunAnalysis(ITextSource textSource, CSharpFullParseInformation parseInfo)
{
if (markerService == null)
return;
if (cancellationTokenSource != null)
cancellationTokenSource.Cancel();
cancellationTokenSource = new CancellationTokenSource();
var cancellationToken = cancellationTokenSource.Token;
List<InspectionTag> results = new List<InspectionTag>();
try {
await Task.Run(
delegate {
var compilation = ParserService.GetCompilationForFile(parseInfo.FileName);
var resolver = parseInfo.GetResolver(compilation);
var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken);
foreach (var inspector in inspectors.Value) {
foreach (var issue in inspector.Run(context)) {
results.Add(new InspectionTag(
inspector,
issue.Title,
context.GetOffset(issue.Start),
context.GetOffset(issue.End),
issue.Fix != null));
}
}
}, cancellationToken);
} catch (TaskCanceledException) {
}
if (!cancellationToken.IsCancellationRequested) {
analyzedVersion = textSource.Version;
Clear();
foreach (var newResult in results) {
newResult.CreateMarker(textSource.Version, editor.Document, markerService);
}
existingResults = results;
}
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
}
}
}

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

@ -24,7 +24,6 @@ namespace CSharpBinding.Refactoring @@ -24,7 +24,6 @@ namespace CSharpBinding.Refactoring
readonly ITextSource textSource;
readonly TextLocation location;
volatile IDocument document;
readonly CSharpAstResolver resolver;
int selectionStart, selectionLength;
public SDRefactoringContext(ITextSource textSource, CSharpAstResolver resolver, TextLocation location, int selectionStart, int selectionLength, CancellationToken cancellationToken)
@ -32,7 +31,6 @@ namespace CSharpBinding.Refactoring @@ -32,7 +31,6 @@ namespace CSharpBinding.Refactoring
{
this.textSource = textSource;
this.document = textSource as IDocument;
this.resolver = resolver;
this.selectionStart = selectionStart;
this.selectionLength = selectionLength;
this.location = location;
@ -44,7 +42,6 @@ namespace CSharpBinding.Refactoring @@ -44,7 +42,6 @@ namespace CSharpBinding.Refactoring
this.editor = editor;
this.textSource = editor.Document;
this.document = editor.Document;
this.resolver = resolver;
this.selectionStart = editor.SelectionStart;
this.selectionLength = editor.SelectionLength;
this.location = location;

14
src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs

@ -75,17 +75,17 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -75,17 +75,17 @@ namespace ICSharpCode.SharpDevelop.Parser
ITextSource content;
ParseInformation parseInformation;
public ParserUpdateStepEventArgs(FileName fileName, ITextSource content, ParseInformation parsedFile)
public ParserUpdateStepEventArgs(FileName fileName, ITextSource content, ParseInformation parseInformation)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (content == null)
throw new ArgumentNullException("content");
if (parsedFile == null)
throw new ArgumentNullException("parsedFile");
if (parseInformation == null)
throw new ArgumentNullException("parseInformation");
this.fileName = fileName;
this.content = content;
this.parseInformation = parsedFile;
this.parseInformation = parseInformation;
}
public FileName FileName {
@ -100,6 +100,12 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -100,6 +100,12 @@ namespace ICSharpCode.SharpDevelop.Parser
}
}
public ParseInformation ParseInformation {
get {
return parseInformation;
}
}
public IParsedFile ParsedFile {
get {
return parseInformation.ParsedFile;

Loading…
Cancel
Save