The Syntax API allows you to look at the structure of a program, but sometimes, you will need more information about the semantics or meaning of a program. For example, you can't track down the references to members within your source code with syntax APIs.
Let's consider a simple Hello World program to analyze.
static void SemanticAnalysisExample1()
{
    SyntaxTree tree = CSharpSyntaxTree.ParseText(
@"using System;
using System.Collections.Generic;
using System.Text;
 
namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(""Hello, World!"");
        }
    }
}");
    var root = (CompilationUnitSyntax)tree.GetRoot();
    var compilation = CSharpCompilation.Create("HelloWorld")
        .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location))
        .AddSyntaxTrees(tree);
    var model = compilation.GetSemanticModel(tree);
    var nameInfo = model.GetSymbolInfo(root.Usings[0].Name);
    var systemSymbol = (INamespaceSymbol)nameInfo.Symbol;
    var nsMembers = systemSymbol.GetNamespaceMembers();
    foreach (var ns in nsMembers)
    {
        Console.WriteLine(ns.Name);
    }
}
The above code will first parse the source code to the SyntaxTree and then create a compilation of the syntax tree. Let's execute the above code, and it will enumerate the sub-namespaces of the System namespace and print their names to the console.
Buffers
CodeDom
Collections
ComponentModel
Configuration
Diagnostics
Globalization
IO
Net
Numerics
Private
Reflection
Resources
Runtime
Security
StubHelpers
Text
Threading