I am using Roslyn to gather all the invocations of methods in a method and replace them with shims in the corresponding test method for the method. The problem is that in spite of initializing the compilation object appropriately with all the references and syntax trees of the project, it throws an ArgumentException which says "Syntax node is not within Syntax tree".
This is the code that I have used to initialize the semantic model:
public TestMethodCodeGenerator(string code, Project project = null)
{
if (!string.IsNullOrWhiteSpace(code))
{
var syntaxTree = CSharpSyntaxTree.ParseText(code);
if (null != project)
{
var syntaxTreesOfDocumentsInProject = new List<SyntaxTree>();
foreach (var document in project.Documents)
{
syntaxTreesOfDocumentsInProject.Add(CSharpSyntaxTree.ParseFile(document.FilePath));
}
var compilation = CSharpCompilation.Create("Demo").AddReferences(project.MetadataReferences).AddSyntaxTrees(syntaxTreesOfDocumentsInProject);
this.semanticModel = compilation.GetSemanticModel(syntaxTreesOfDocumentsInProject[0]);
}
}
else
{
var compilation = CSharpCompilation.Create("Demo").AddSyntaxTrees(syntaxTree);
this.semanticModel = compilation.GetSemanticModel(syntaxTree);
}
}
}
This is how I have used the semanticModel to generate shims for all invocations:
private string PopulateMethodBodyWithShims(MethodDeclarationSyntax methodDeclarationSyntax)
{
if (null != methodDeclarationSyntax)
{
var stringBuilder = new StringBuilder();
var methodBlock = methodDeclarationSyntax.Body;
foreach (var statement in methodBlock.Statements)
{
var invocationSyntax = this.ExtractMethodInvocationSyntaxFromStatement(statement);
if (null != invocationSyntax)
{
var call = invocationSyntax.Expression as MemberAccessExpressionSyntax;
if (null != call)
{
try
{
IMethodSymbol methodSymbol;
**methodSymbol = this.semanticModel.GetSymbolInfo(call).Symbol as IMethodSymbol;**
if (null != methodSymbol)
{
var shimMethod = this.GenerateShimMethod(methodSymbol);
stringBuilder.AppendLine(GeneratedTestClassConstants.IndentationSpaceToken + GeneratedTestClassConstants.IndentationSpaceToken + shimMethod);
}
}
catch (ArgumentException ex)
{
////This exception can be thrown if the syntax node is not within the syntax tree
var message = ex.Message;
throw new ArgumentException(message + " : " + call);
}
}
}
}
.
.
.
The highlighted region in the second code snippet is where the exception occurs and execution flows to the catch block. What is the issue and what am I missing here?