2017-08-10 4 views
1

Supposons que j'ai un appel dans le code, SomeClass.SomeStaticMethod<T>(), qui est une InvocationExpressionSyntax.C# Roslyn Compiler - Comment obtenir l'espace de noms d'un type à partir de IdentifierNameSyntax?

Je reçois le nom du type générique T en tant que chaîne (à partir de IdentifierNameSyntax). J'ai essayé d'obtenir le symbole de T mais je n'ai pas réussi.

Comment puis-je trouver les informations d'espace de noms de type T?

MISE À JOUR: @ La réponse de SJP est correcte. Je veux expliquer mon erreur pour ceux qui veulent obtenir de l'information d'espace de noms de IdentifierNameSyntax, qui contient un identificateur pour une classe (nom de la classe):

Mon objectif initial était de trouver des invocations dans SomeClass.SomeMethod<T>() le format et obtenir des informations d'espace de noms de type T.

var namedTypeSymbol = context.Symbol as INamedTypeSymbol; 
var reference = nameTypeSymbol.DeclaringSyntaxReferences.First(); 
var classSyntaxTree = reference.SyntaxTree; 

var semanticModel = context.Compilation.GetSemanticModel(classSyntaxTree); 
var genericNameSyntax = (GenericNameSyntax)((MemberAccessExpressionSyntax)node.Expression).Name; 
var identifierNameSyntax = genericNameSyntax.TypeArgumentList.Arguments.First(); 
var typeInfo = semanticModel.GetTypeInfo(identifierNameSyntax); 
var nameSpace = ((INamedTypeSymbol)typeInfo.Type).ContainingNamespace; 
var nameSpaceName = nameSpace.ToString(); 

Voici mon erreur:

J'ai essayé de l'espace de noms complet comme <module_name>.<namespace_part_1>.<namespace_part_2> mais quand je l'ai fait namedTypeSymbol.ContainingNamespace.Name, je me suis seulement <namespace_part_2> . Après quelques heures, j'ai trouvé que l'obtention de l'espace de noms complet est faite comme namedTypeSymbol.ContainingNamespace.ToString().

Parfois, la meilleure chose à faire est de sortir et de prendre l'air frais :)

Répondre

2

Vous allez avoir besoin du modèle sémantique pour atteindre votre tâche. En supposant que vous avez besoin l'espace de noms SomeClass, vous pouvez simplement obtenir le type et le nom à partir de là l'espace de noms du MemberAccessExpressionSyntax en accédant au nom du champ de l'expression comme suit:

var semanticModel = await document.GetSemanticModelAsync() 
var name = (GenericNameSyntax)((MemberAccessExpressionSyntax)node.Expression).Name; 
var typeInfo = semanticModel.GetTypeInfo(name.TypeArgumentList.Arguments.First()); 
var nameSpace = ((INamedTypeSymbol)typeInfo.Type).ContainingNamespace; 
var nameSpaceName = nameSpace.Name; 

Pour le programme exemple suivant cela entraînerait dans "Système" ou "ConsoleApp1" (selon l'appel) pour la variable nomSpaceName alors que toutes les autres informations peuvent être accédées par la variable nomSpace.

namespace ConsoleApp1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Program.DoStuff<string>(); 
      Program.DoStuff<Program>(); 
     } 

     static void DoStuff<T>() 
     { 

     } 
    } 
} 
+2

Oui, OP a besoin du modèle sémantique. Mais il a besoin de GetSymbolInfo sur l'invocation elle-même, puis du paramètre IMethodSymbol le premier type. Je suppose que la question n'était pas claire auparavant en raison d'un mauvais formatage, mais j'ai corrigé cela maintenant. –

+0

Bien obligé, je n'ai pas reconnu l'intention originale de la question posée. J'ai ajusté le code en conséquence. – SJP

+0

@SJP Belle façon mieux maintenant –