2017-09-20 2 views
0

Je modifie mon analyseur de code précédent en C# en utilisant Roslyn et encore une fois je suis coincé avec quelques changements que je ne sais pas exactement comment appliquer.Modifier le paramètre de déclaration de fonction en ajoutant l'attribut et la valeur par défaut dans Roslyn C#

sur Fonder: https://github.com/dotnet/roslyn/wiki/Getting-Started-C%23-Syntax-Analysis J'ai créé une base pour travailler dans cette question: Finding all not inheriting C# classes with Roslyn and changing to inheriting from base object (java-like)

Je l'ai analysé et traversé l'arbre pour trouver toutes les déclarations de méthodes et leurs paramètres. Sur VS Syntaxe Fonder Visualiseur J'ai construit ceci:

foreach (var c in root1.DescendantNodesAndSelf()) 
{ 
    var methodDeclaration = c as MethodDeclarationSyntax; 

    if (methodDeclaration == null) 
     continue; 

    if (methodDeclaration.ParameterList != null) //Have parameters 
    { 
     foreach (var p in methodDeclaration.ParameterList.Parameters) 
     { 
      var parameter = p as ParameterSyntax; 
      String name, type; 
      name = parameter.GetLastToken().Value.ToString(); 
      type = parameter.GetFirstToken().Value.ToString(); 

      if (parameter == null) 
       continue; 

      if (name == "caller" && type == "string") 
      { 
       AttributeSyntax ats = SyntaxFactory.Attribute(SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System.Runtime.CompilerServices"),SyntaxFactory.IdentifierName("CallerMemberName"))); 
       SeparatedSyntaxList<AttributeSyntax> ssl = new SeparatedSyntaxList<AttributeSyntax>(); 
       ssl = ssl.Add(ats); 
       AttributeListSyntax als = SyntaxFactory.AttributeList(ssl); 
       var par1 = parameter.AddAttributeLists(als); 
       //ExpressionSyntax es = SyntaxFactory.AssignmentExpression(SyntaxKind.EqualsValueClause,null,SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression)) 
       //SyntaxFactory.EqualsValueClause(es); 
       par1 = par1.AddModifiers(); 
       root2 = root2.ReplaceNode(parameter, par1); 
      } 
     } 
    } 
    else //Don't have parameters 
     continue; 

} 

Je suis en train de convertir une méthode déclarée comme ceci:

private void testM3(string caller) 

dans

private void testM3([System.Runtime.CompilerServices.CallerMemberName] string caller = "") 

Et cette partie:

//ExpressionSyntax es = SyntaxFactory.AssignmentExpression(SyntaxKind.EqualsValueClause,null,SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression)) 
//SyntaxFactory.EqualsValueClause(es); 

est ma tentative ratée d'ach ieve création d'un nœud égal.

D'après ce que je comprends, cette partie:

AttributeSyntax ats = SyntaxFactory.Attribute(SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System.Runtime.CompilerServices"),SyntaxFactory.IdentifierName("CallerMemberName"))); 
SeparatedSyntaxList<AttributeSyntax> ssl = new SeparatedSyntaxList<AttributeSyntax>(); 
ssl = ssl.Add(ats); 
AttributeListSyntax als = SyntaxFactory.AttributeList(ssl); 
var par1 = parameter.AddAttributeLists(als); 

me donnera un nouveau noeud de paramètre dans var par1 qui comprend déjà attribut, donc je dois d'ajouter un paramètre de valeur par défaut. Veuillez me corriger si je me trompe sur cet attribut, et j'aimerais savoir comment construire correctement ce nœud d'expression.

Répondre

1

Vous avez une deux erreurs:

  • System.Runtime.CompilerServices.CallerMemberName est QualifiedName qui contient System.Runtime.CompilerServices comme QualifiedName et CallerMemberName comme IdentifierName. System.Runtime.CompilerServices contient System.Runtime comme QualifiedName et CompilerServices comme IdentifierName.Et enfin System.Runtime contient deux IdentifierName.

    Vous avez donc besoin de fixer la création de AttributeSyntax comme celles-ci figurent dans le code ci-dessous:

    AttributeSyntax ats = SyntaxFactory.Attribute(
             SyntaxFactory.QualifiedName(
              SyntaxFactory.QualifiedName(
               SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Runtime")), 
               SyntaxFactory.IdentifierName("CompilerServices")), 
             SyntaxFactory.IdentifierName("CallerMemberName"))); 
    
  • EqualsValueClause ne doit pas contenir AssignmentExpression, mais devrait contenir un certain type de LiteralExpression directement. Dans votre cas, il est StringLiteralExpression:

    var par1 = parameter 
            .AddAttributeLists(als) 
            .WithDefault(SyntaxFactory.EqualsValueClause(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("")))); 
    

Par ailleurs, vous pouvez utiliser une certaine méthode utile de nœuds, comme par exemple ParameterSyntax.WithDefault, pour créer une copie de noeud (SyntaxTree est immuable dans Roslyn) quand vous voulez pour appliquer un petit changement au nœud existant, puis le repasser.

0

Si vous jetez un oeil à la Roslyn Quoter pour la méthode suivante, vous pouvez obtenir le code nécessaire pour générer le code désiré:

public void GetSomething([CallerMemberName] string test=""){ 

} 

Vous remarquerez que la valeur par défaut dans le paramètre est construit en utilisant les éléments suivants méthode (le quoter Roslyn omet généralement le SyntaxFactory):

.WithDefault(SyntaxFactory.EqualsValueClause(
        SyntaxFactory.LiteralExpression(
          SyntaxKind.StringLiteralExpression, 
          SyntaxFactory.Literal("") 
          ) 
        ) 
      ); 

Ainsi, afin d'ajouter votre EqualsValueClause par défaut il vous suffit de remplacer la valeur par défaut existante en appelant le code ci-dessus sur votre paramètre (au lieu du unc Code ommented):

par1 = par1.WithDefault(SyntaxFactory.EqualsValueClause(
        SyntaxFactory.LiteralExpression(
          SyntaxKind.StringLiteralExpression, 
          SyntaxFactory.Literal("") 
          ) 
        ) 
      );