public Solution SafelyRefactorSolution(Solution solution, Document document, int index) { var numInitialErrors = solution.CompilationErrorCount(); var oldErrors = solution.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error).Select(a => a.Id); var oldSolution = solution; try { solution = ExecuteRefactoring(document, solution, index); var oldFile= document.GetTextAsync().Result; var newFile = solution.GetDocument(document.Id).GetTextAsync().Result; if (solution.CompilationErrorCount() > numInitialErrors) { Fail.Info("{0}", document.FilePath); Fail.Info("{0}\r\n*************************************************************************************************", oldFile); Fail.Info("{0}\r\n=================================================================================================", newFile); Fail.Error("=============================================SOLUTIONERRORS======================================================="); foreach ( var diagnostic in solution.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error && !oldErrors.Any(a=> a.Equals(d.Id)))) { Fail.Error("{0}", diagnostic); } Fail.Error("========================================================================================================================="); CompilationError = true; RefactoredSolution = solution; solution = oldSolution; } else { Success.Info("{0}", document.FilePath); Success.Info("{0}\r\n*************************************************************************************************", oldFile); Success.Info("{0}\r\n=================================================================================================", newFile); RefactoredSolution = solution; NumMethodSymbolLookups += SemanticModelExtensions.NumMethodSymbolLookups; SemanticModelExtensions.ResetSymbolLookupCounter(); } } catch (RefactoringException e) { Logger.Error("Refactoring failed: index={0}: {1}: {2}", index, e.Message, e); solution = oldSolution; RefactoringExceptionWasThrown = true; } catch (NotImplementedException e) { Logger.Error("Not implemented: index={0}: {1}: {2}", index, e.Message, e); solution = oldSolution; NotImplementedExceptionWasThrown = true; } catch (PreconditionException e) { Logger.Error("Precondition failed: {0}: {1}", e.Message, e); solution = oldSolution; PreconditionFailed = true; } catch (Exception e) { Logger.Error("Unhandled exception while refactoring: index={0}: {1}\n{2}", index, e.Message, e); solution = oldSolution; OtherExceptionWasThrown = true; } return solution; }
public SolutionRefactoring(Workspace workspace) { if (workspace == null) throw new ArgumentNullException("workspace"); _workspace = workspace; _originalSolution = _workspace.CurrentSolution; Solution newSolution = _originalSolution; var projectlist = _originalSolution.Projects.AsEnumerable(); foreach(var project in projectlist) { List<MetadataReference> list = new List<MetadataReference>(); //foreach (var refer in project.MetadataReferences) // // check whether they already reference microsoft.bcl.async // list.Add(refer); if (project.MetadataReferences.Where(a => a.Display.ToString().Contains("AsyncCtpLibrary") || a.Display.ToString().Contains("Microsoft.Bcl.Async")).Any()) continue; if (project.IsWindowsPhoneProject() == 1) { list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.Async.1.0.14-rc\lib\sl4-windowsphone71\Microsoft.Threading.Tasks.dll")); list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.Async.1.0.14-rc\lib\sl4-windowsphone71\Microsoft.Threading.Tasks.Extensions.dll")); list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.Async.1.0.14-rc\lib\sl4-windowsphone71\Microsoft.Threading.Tasks.Extensions.Phone.dll")); list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.1.0.16-rc\lib\sl4-windowsphone71\System.Runtime.dll")); list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.1.0.16-rc\lib\sl4-windowsphone71\System.Threading.Tasks.dll")); } else if (project.IsWindowsPhoneProject() == 2) { list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.Async.1.0.14-rc\lib\wp8\Microsoft.Threading.Tasks.dll")); list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.Async.1.0.14-rc\lib\wp8\Microsoft.Threading.Tasks.Extensions.dll")); list.Add(new MetadataFileReference(@"C:\Users\Semih\Desktop\lib\Microsoft.Bcl.Async.1.0.14-rc\lib\wp8\Microsoft.Threading.Tasks.Extensions.Phone.dll")); } else continue; newSolution = newSolution.AddMetadataReferences(project.Id, list); } if (newSolution.CompilationErrorCount() > _originalSolution.CompilationErrorCount()) { TempLog.Info("{0}", newSolution.FilePath); foreach (var diagnostic in newSolution.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error)) { TempLog.Info("=== Solution error: {0}", diagnostic); } } _originalSolution = newSolution; }
/// <summary> /// Execute the APM-to-async/await refactoring for a given APM method invocation. /// </summary> /// <param name="document">The C# Document on which to operate/in which the Begin and End method calls are represented.</param> /// <param name="solution">The solution that contains the C# document.</param> /// <param name="workspace">The workspace to which the code in the syntax tree currently belongs, for formatting purposes.</param> /// <param name="index">The index number </param> /// <returns>The CompilationUnitSyntax node that is the result of the transformation.</returns> public static CompilationUnitSyntax RefactorToTask(Document document, Solution solution, Workspace workspace, int index) { if (document == null) throw new ArgumentNullException("document"); if (workspace == null) throw new ArgumentNullException("workspace"); String message; var numErrorsInSolutionBeforeRewriting = solution.CompilationErrorCount(); var syntaxTree = (SyntaxTree)document.GetSyntaxTreeAsync().Result; var syntax = (CompilationUnitSyntax)syntaxTree.GetRoot(); Logger.Trace("\n### REFACTORING CODE ###\n{0}\n### END OF CODE ###", syntax.Format(workspace)); InvocationExpressionSyntax beginXxxCall; try { beginXxxCall = document.GetAnnotatedInvocation(index); } catch (InvalidOperationException) { throw new ArgumentException( "Syntax tree has no InvocationExpressionSyntax node annotated with RefactorableAPMInstance"); } var model = (SemanticModel)document.GetSemanticModelAsync().Result; var callbackArgument = FindAsyncCallbackInvocationArgument(model, beginXxxCall); var callbackExpression = callbackArgument.Expression; CompilationUnitSyntax rewrittenSyntax; switch (callbackExpression.CSharpKind()) { case SyntaxKind.SimpleLambdaExpression: var lambda = (SimpleLambdaExpressionSyntax)callbackExpression; switch (lambda.Body.CSharpKind()) { case SyntaxKind.Block: var stateArgument = FindAsyncStateInvocationArgument(model, beginXxxCall); switch (stateArgument.Expression.CSharpKind()) { case SyntaxKind.NullLiteralExpression: Logger.Info("Refactoring:\n{0}", beginXxxCall.ContainingMethod()); return RefactorSimpleLambdaInstance(syntax, beginXxxCall, model, workspace, callbackArgument); default: Logger.Info("Rewriting to remove state argument:\n{0}", beginXxxCall); rewrittenSyntax = RewriteStateArgumentToNull(lambda, syntax, stateArgument); break; } break; case SyntaxKind.InvocationExpression: Logger.Info("Rewriting lambda to block form:\n{0}", beginXxxCall); rewrittenSyntax = RewriteInvocationExpressionToBlock(syntax, lambda, model, beginXxxCall); break; default: message = String .Format( "Unsupported lambda body kind: {0}: method:\n{1}", lambda.Body.CSharpKind(), beginXxxCall.ContainingMethod() ); Logger.Error("Not implemented: {0}", message); throw new NotImplementedException(message); } break; case SyntaxKind.IdentifierName: case SyntaxKind.SimpleMemberAccessExpression: Logger.Info("Rewriting method reference to lambda:\n{0}", beginXxxCall); rewrittenSyntax = RewriteMethodReferenceToSimpleLambda(syntax, beginXxxCall, model, callbackArgument, callbackExpression); break; case SyntaxKind.ParenthesizedLambdaExpression: Logger.Info("Rewriting parenthesized lambda to simple lambda:\n{0}", beginXxxCall); rewrittenSyntax = RewriteParenthesizedLambdaToSimpleLambda(syntax, beginXxxCall, model); break; case SyntaxKind.ObjectCreationExpression: Logger.Info("Rewriting object creation expression to simple lambda:\n{0}", beginXxxCall); var objectCreation = (ObjectCreationExpressionSyntax)callbackExpression; rewrittenSyntax = RewriteObjectCreationToSimpleLambda(syntax, objectCreation, workspace); break; case SyntaxKind.AnonymousMethodExpression: Logger.Info("Rewriting anonymous method (delegate) expression to simple lambda:\n{0}", beginXxxCall); var anonymousMethod = (AnonymousMethodExpressionSyntax)callbackExpression; rewrittenSyntax = RewriteAnonymousMethodToSimpleLambda(syntax, anonymousMethod, workspace); break; case SyntaxKind.NullLiteralExpression: message = String.Format("callback is null:\n{0}", beginXxxCall.ContainingMethod()); Logger.Error("Precondition failed: {0}", message); throw new PreconditionException(message); case SyntaxKind.InvocationExpression: message = String .Format( "InvocationExpression as callback is not supported: {0}", beginXxxCall ); Logger.Error("Precondition failed: {0}", message); throw new PreconditionException(message); case SyntaxKind.GenericName: message = String.Format("GenericName syntax kind is not supported"); Logger.Error("Precondition failed: {0}", message); throw new PreconditionException(message); default: message = String.Format( "Unsupported actual argument syntax node kind: {0}: callback argument: {1}: in method:\n{2}", callbackExpression.CSharpKind(), callbackArgument, beginXxxCall.ContainingMethod() ); Logger.Error(message); throw new NotImplementedException(message); } var rewrittenDocument = document.WithSyntaxRoot(rewrittenSyntax); var rewrittenSolution = solution.WithDocumentSyntaxRoot(document.Id, rewrittenSyntax); //if (rewrittenSolution.CompilationErrorCount() > numErrorsInSolutionBeforeRewriting) //{ // Logger.Error( // "Rewritten solution contains more compilation errors than the original solution while refactoring: {0} @ {1}:{2} in method:\n{3}", // beginXxxCall, // beginXxxCall.SyntaxTree.FilePath, // beginXxxCall.GetStartLineNumber(), // beginXxxCall.ContainingMethod() // ); // Logger.Warn("=== SOLUTION ERRORS ==="); // foreach (var diagnostic in rewrittenSolution.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error)) // { // Logger.Warn(" - {0}", diagnostic); // } // Logger.Warn("=== END OF SOLUTION ERRORS ==="); // Logger.Warn("\n### ORIGINAL CODE ###\n{0}### END OF CODE ###", syntax.Format(workspace)); // Logger.Warn("\n### REWRITTEN CODE ###\n{0}### END OF CODE ###", rewrittenSyntax.Format(workspace)); // throw new RefactoringException("Rewritten solution contains more compilation errors than the original refactoring"); //} return null; }