#develop (short for SharpDevelop) is a free IDE for .NET programming languages.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

152 lines
6.0 KiB

/*
* Created by SharpDevelop.
* User: Daniel
* Date: 9/22/2012
* Time: 12:42 PM
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.PatternMatching;
using ICSharpCode.NRefactory.Refactoring;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.SharpDevelop;
namespace PortSD4AddInToSD5
{
[IssueDescription ("Usage of SD4 WorkbenchSingleton",
Description = "Usage of SD4 WorkbenchSingleton",
Category = "SD4->SD5",
Severity = Severity.Warning)]
public class WorkbenchSingletonIssueProvider : CodeIssueProvider
{
public override IEnumerable<CodeIssue> GetIssues(BaseRefactoringContext context, string subIssue = null)
{
foreach (var mre in context.RootNode.Descendants.OfType<MemberReferenceExpression>()) {
var rr = context.Resolve(mre);
var mrr = rr as MemberResolveResult;
if (mrr == null)
continue;
switch (mrr.Member.FullName) {
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainWin32Window":
yield return Issue(
mre,
script => {
script.Replace(mre, new IdentifierExpression("SD").Member("WinForms").Member("MainWin32Window"));
});
break;
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.Workbench":
yield return Issue(
mre,
script => {
script.Replace(mre, new IdentifierExpression("SD").Member("Workbench"));
});
break;
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.StatusBar":
yield return Issue(
mre,
script => {
script.Replace(mre, new IdentifierExpression("SD").Member("StatusBar"));
});
break;
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.InvokeRequired":
yield return Issue(
mre,
script => {
script.Replace(mre, new IdentifierExpression("SD").Member("MainThread").Member("InvokeRequired"));
});
break;
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainWindow":
yield return Issue(
mre,
script => {
script.Replace(mre, new IdentifierExpression("SD").Member("Workbench").Member("MainWindow"));
});
break;
}
}
foreach (var invocationExpression in context.RootNode.Descendants.OfType<InvocationExpression>()) {
var rr = context.Resolve(invocationExpression);
var irr = rr as CSharpInvocationResolveResult;
if (irr == null)
continue;
switch (irr.Member.FullName) {
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.CallLater":
yield return Issue(
invocationExpression,
script => {
script.Replace(invocationExpression,
new IdentifierExpression("SD").Member("MainThread").Invoke("CallLater", invocationExpression.Arguments.Select(e => e.Clone())));
});
break;
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.AssertMainThread":
yield return Issue(
invocationExpression,
script => {
script.Replace(invocationExpression,
new IdentifierExpression("SD").Member("MainThread").Invoke("VerifyAccess"));
});
break;
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.SafeThreadAsyncCall":
{
// SD.MainThread.InvokeAsync(argument).FireAndForget();
Expression arg = invocationExpression.Arguments.First().Clone();
if (invocationExpression.Arguments.Count > 1)
arg = new LambdaExpression { Body = arg.Invoke(invocationExpression.Arguments.Skip(1).Select(a => a.Clone())) };
yield return Issue(
invocationExpression,
script => {
script.Replace(invocationExpression,
new IdentifierExpression("SD").Member("MainThread")
.Invoke("InvokeAsyncAndForget", arg));
});
break;
}
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.SafeThreadCall":
case "ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.SafeThreadFunction":
{
// SD.MainThread.InvokeIfRequired(argument);
Expression arg = invocationExpression.Arguments.First().Clone();
if (invocationExpression.Arguments.Count > 1)
arg = new LambdaExpression { Body = arg.Invoke(invocationExpression.Arguments.Skip(1).Select(a => a.Clone())) };
yield return Issue(
invocationExpression,
script => {
script.Replace(invocationExpression,
new IdentifierExpression("SD").Member("MainThread").Invoke("InvokeIfRequired", arg));
});
break;
}
case "ICSharpCode.SharpDevelop.IMessageLoop.InvokeAsync":
// We used to recommend SD.MainThread.InvokeAsync(...).FireAndForget(),
// but it's better to use SD.MainThread.InvokeAsyncAndForget(...)
if (invocationExpression.Clone().Invoke("FireAndForget").IsMatch(invocationExpression.Parent.Parent)) {
var ident = invocationExpression.Parent.GetChildByRole(Roles.Identifier);
yield return new CodeIssue(
ident.StartLocation, ident.EndLocation,
"Use InvokeAsyncAndForget() instead",
new CodeAction("Use InvokeAsyncAndForget() instead",
script => {
var newInvocation = (InvocationExpression)invocationExpression.Clone();
((MemberReferenceExpression)newInvocation.Target).MemberName = "InvokeAsyncAndForget";
script.Replace(invocationExpression.Parent.Parent, newInvocation);
},
ident));
}
break;
}
}
}
CodeIssue Issue(AstNode node, Action<Script> fix = null)
{
return new CodeIssue(node.StartLocation, node.EndLocation, "WorkbenchSingleton is obsolete",
fix != null ? new CodeAction("Use SD5 API", fix, node) : null);
}
}
}