
Kevin Erath
Geschäftsführer
Veröffentlicht am
22. Mai 2021

Vor kurzem habe ich mithilfe von Roslyn gezeigt, wie ein Quellcode nach Ausnahmen durchsucht werden kann. Hierzu habe ich den Syntaxbaum von Roslyn verwendet. Dieser liefert Informationen zum lexikalischen und syntaktischen Aufbau eines Quellcodes. Möchte man weitere Details über einen Syntax-Knoten erhalten, so ist dieser aber nicht ausreichend. Im genannten Beispiel war es z.B. nicht möglich den Namensraum der geworfenen Ausnahmen zu ermitteln. Um an diese Informationen zu kommen wird das semantische Modell benötigt. Das semantische Modell wird von Roslyn während des Kompiliervorgangs erstellt.
Dies klingt allerdings komplizierter als es ist. So kann das semantische Modell durch Aufruf der Methode GetSemanticModelAsync()
für ein Dokument abgerufen werden.
var filename = ...;
var ws = MSBuildWorkspace.Create();
var project = ws.OpenProjectAsync(filename).Result;
var document = project.Documents.First();
var model = document.GetSemanticModelAsync().Result;
Das semantische Modell besteht aus Symbolen. Ein Symbol entspricht dabei jeweils einem vom Compiler gefundenem Element, wie z.B. einer Klasse, Variablen oder Methode. Die enthaltenen Informationen unterscheiden sich zwar je nach Element, aber es gibt auch Informationen die bei allen Symbolen zur Verfügung stehen. Dies sind beispielsweise der Ort (Stelle im Quellcode bzw. in einem externen Verweis, sowie der umschließende Namensraum) oder Modifikatoren wie public
, protected
, static
oder abstract
. Weitere Informationen kommen dann je nach Symboltyp hinzu. So hat ein Symbol für eine Methode Informationen über die Übergabeparameter und dessen Rückgabewert.
Um das Symbol für einen Syntax-Knoten zu erhalten, reicht es eine Methode auf dem semantischen Modell aufzurufen. Je nach Art des Syntax-Knotens muss zwischen den beiden Methoden GetDeclaredSymbol()
und GetSymbolInfo()
unterschieden werden. Erstere dient zum Abrufen des Symbols für Deklarationen wie z.B. einer Klassen- oder Methodendeklaration. Die zweite Methode kommt dann zum Einsatz, wenn das Symbol für einen Ausdruck, wie einen Methodenaufruf, abgefragt werden soll.
Das kürzlich gezeigte Programm zur Auflistung von Ausnahmen lässt sich leicht, um die Fähigkeit den Namensraum anzuzeigen, erweitern. Hierzu muss zuerst die Klasse DocumentInfo
um die Eigenschaft Model
für das Speichern des SemanticModel
erweitert werden:
public class DocumentInfo
{
public SyntaxNode Node { get; set; }
public SemanticModel Model { get; set; }
}
Diese Eigenschaft kann dann in der Methode OpenAllDocuments()
mit dem entsprechenden Modell befüllt werden:
private static IEnumerable<DocumentInfo> OpenAllDocuments(
IEnumerable<Project> projects)
{
var documents = projects.SelectMany(x => x.Documents);
return documents.Select(x => new DocumentInfo {
Node = x.GetSyntaxRootAsync().Result,
Model = x.GetSemanticModelAsync().Result});
}
Als letztes wird die Methode FindExceptions()
angepasst. Diese soll nun über das Modell den Namensraum der Ausnahme ermitteln. Bisher wurde dort nur der Name über den Syntax-Knoten ermittelt:
...
foreach (var stmt in throwStatements)
{
var objCreation = stmt.DescendantNodes().
OfType<ObjectCreationExpressionSyntax>().FirstOrDefault();
if (objCreation != null)
{
var model = element.Parent.Document.Model;
var symbolInfo = model.GetSymbolInfo(objCreation);
var type = symbolInfo.Symbol.ContainingType;
nodeDesc.Add(type.ContainingNamespace + "." + type.Name);
}
}
...
Natürlich ist der Quellcode des kompletten Programms wieder auf Github verfügbar. Ich hoffe, ich konnte einen kleinen Einblick in das semantische Modell geben.

Hier schreibt
Kevin Erath
Als Mitbegründer und Geschäftsführer von pep.digital verbringe ich zwar nicht mehr jeden Tag ausschließlich damit, coole Lösungen für unsere Kunden zu realisieren. Trotzdem finde ich immer wieder die Zeit, mich auch mal tiefer in die Technik einzutauchen und meine Erkenntnisse hier im Blog zu teilen. Und ehrlich gesagt, das Unternehmen und unsere tollen Mitarbeiter:innen weiterzuentwickeln, macht mir mindestens genauso viel Spaß.
Quellen
Weitere interessante Artikel
Wir möchten hier nicht nur über Neuigkeiten aus dem Unternehmen berichten, sondern auch das Wissen und die Erfahrung unserer Experten teilen.

MVP – Das Minimum Viable Product und die Musik
So wie ein Klavierspieler keine ganze Band ersetzen kann, kann das MVP eines Softwareprodukts nicht den Endausbau darstellen. In beiden Fällen wird das Ergebnis nur attraktiv, wenn man sich trotzdem um alle Aspekte kümmert.

Steffen Ehlers
Geschäftsführer

Debugging von Java Apps in Docker Containern
Wie kann ich meine dockerisierte Java-Anwendung mit IntelliJ IDEA oder Eclipse debuggen? Und wie bekomme ich IntelliJ IDEA dazu, dass Änderungen am Code während des Debuggens automatisch neu compiliert und deployt werden, ohne dass der Debug-Prozess neu gestartet werden muss?

Dirk Randhahn
Teamleiter, Softwarearchitekt