text: Learn Roslyn Now: Part 7 Introducing the Semantic Model – Shotgun Debugging
  Learn Roslyn Now: Part 7 Introducing the Semantic Model
  joshvarty	Uncategorized	 October 30, 2014 September 7, 2016 2 Minutes
  Up until this point we've been working with C# code on a purely syntactical level. We can find property declarations, but we can't track down references to this property within our source code. We can identify invocations, but we can't tell what's being invoked. And God help us if we want to try to solve the really hard problems like overload resolution.
  In this developer's opinion, the semantic layer is where the power of Roslyn really shines. Roslyn's semantic model can answer all the hard compile-time questions we might have. However, this power comes at a cost. Querying the semantic model is typically more expensive than querying syntax trees. This is because requesting a semantic model often triggers a compilation.
  There are 3 different ways to request the semantic model:
  1. Document.GetSemanticModel()
  2. Compilation.GetSemanticModel(SyntaxTree)
  3. Various Diagnostic AnalysisContexts including CodeBlockStartAnalysisContext.SemanticModel and SemanticModelAnalysisContext.SemanticModel
  To avoid the boiler plate involved in setting up our own Workspace, we'll simply create compilations for individual syntax trees as follows:
  int MyMethod() { return 0; }
  //Note that we must specify the tree for which we want the model.
  //Each tree has its own semantic model
  Before continuing, it's worth taking a moment to discuss Symbols.
  C# programs are comprised of unique elements, such as types, methods, properties and so on. Symbols represent most everything the compiler knows about each of these unique elements.
  At a high level, every symbol contains information about:
  Where this elements is declared in source or metadata (It may have come from an external assembly)
  What namespace and type this symbol exists within
  Various truths about the symbol being abstract, static, sealed etc.
  More information may be found in ISymbol.
  Other, more context-dependent information may also be uncovered. When dealing with methods, IMethodSymbol allows us to determine:
  Whether the method hides a base method.
  The symbol representing the return type of the method.
  The extension method from which this symbol was reduced.
  The semantic model is our bridge between the world of syntax and the world of symbols.
  SemanticModel.GetDeclaredSymbol() accepts declaration syntax and provides the corresponding symbol.
  SemanticModel.GetSymbolInfo() accepts expression syntax (eg. InvocationExpressionSyntax) and returns a symbol. If the model could not successfully resolve a symbol, it provides candidate symbols which can serve as best guesses.
  Below, we retrieve the symbol for a method via it's declaration syntax. We then retrieve the same symbol, but via an invocation (InvocationExpressionSyntax) instead.
  int x = Method1();
  //Looking at the first method symbol
  var methodSyntax = tree.GetRoot().DescendantNodes().OfType<MethodDeclarationSyntax>().First();
  var methodSymbol = model.GetDeclaredSymbol(methodSyntax);
  Console.WriteLine(methodSymbol.ToString()); //MyClass.Method1()
  Console.WriteLine(methodSymbol.ContainingSymbol); //MyClass
  Console.WriteLine(methodSymbol.IsAbstract); //false
  //Looking at the first invocation
  var invocationSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().First();
  var invokedSymbol = model.GetSymbolInfo(invocationSyntax).Symbol; //Same as MyClass.Method1
  Console.WriteLine(invokedSymbol.ToString()); //MyClass.Method1()
  Console.WriteLine(invokedSymbol.ContainingSymbol); //MyClass
  Console.WriteLine(invokedSymbol.IsAbstract); //false
  Console.WriteLine(invokedSymbol.Equals(methodSymbol)); //true
  The documentation for SemanticNode notes the following:
  An instance of SemanticModel caches local symbols and semantic information. Thus, it is much more efficient to use a single instance of SemanticModel when asking multiple questions about a syntax tree, because information from the first question may be reused. This also means that holding onto an instance of SemanticModel for a long time may keep a significant amount of memory from being garbage collected.
  Essentially, Roslyn is allowing you to make the tradeoff between memory and computation. When querying the semantic model repetitively, it may be in your best interest to keep an instance of it around, instead of requesting a new model from a compilation or document.
  We've only scratched the surface of the Semantic Model. Next time we'll take a look at the control and data flow analysis APIs.
  Published October 30, 2014 September 7, 2016
  Previous Post Learn Roslyn Now: Part 6 Working with Workspaces
  Next Post Code Connect for Visual Studio 2015
  7 thoughts on "Learn Roslyn Now: Part 7 Introducing the Semantic Model"
  PortableExecutableReference.CreateFromAssembly is now obsolete. CreateFromFile appears to be the preferred option.
  Just curious if there is a faster way to get the set of errors than calling compilation.GetDiagnostics() ? Or maybe a hint as to why it's so slow? On a simple example it's taking over 1.1sec to return. To get the diagnostics from the syntax tree it only takes around 50-60msec. It looks like it might be a one-time hit (while it loads additional dlls), but I'm not sure that there's a way to reduce it without keeping the process alive/etc. (Note that I'm trying this with .NET Core, so there could be something with it…) Thanks!
  Looks like it's something to do with using CodeAnalysis from .NET Core. The same test in a .NET Framework console app completes GetDiagnostics() in ~230msec…
  How can I find the list of all method called inside a method?
  If I have got a Solution using MSBuildWorkspace, how can I get SemanticModel from it?
  Each Project has a compilation.
  Each Document has a semantic model.
  So for your case you should be able to go: Workspace > Solution > Project > Document > SemanticModel.
  When SemanticModel.GetDeclaredSymbol() is invoked, is Roslyn performing a whole syntax tree analysis?