private async Task<MethodDeclarationSyntax> GetMethodDeclaration( SyntaxNode node, SemanticModel semanticModel, CancellationToken cancellationToken) { var invocationExpression = node.ChildNodes().FirstOrDefault(n => n.IsKind(SyntaxKind.InvocationExpression)); var methodSymbol = semanticModel.GetSymbolInfo(invocationExpression, cancellationToken).Symbol as IMethodSymbol; if (methodSymbol == null) { return null; } var methodReference = methodSymbol.DeclaringSyntaxReferences.FirstOrDefault(); if (methodReference == null) { return null; } var methodDeclaration = (await methodReference.GetSyntaxAsync(cancellationToken).ConfigureAwait(false)) as MethodDeclarationSyntax; if (methodDeclaration == null) { return null; } if (!methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword))) { return null; } return methodDeclaration; }
private IEnumerable<SyntaxNode> EnumerateNonRootChildren(SyntaxNode node) { foreach (var child in node.ChildNodes()) { if (LambdaUtilities.IsLambdaBodyStatementOrExpression(child)) { continue; } if (HasLabel(child)) { yield return child; } else { foreach (var descendant in child.DescendantNodes(DescendIntoChildren)) { if (HasLabel(descendant)) { yield return descendant; } } } } }
public override void DefaultVisit(SyntaxNode node) { foreach (var child in node.ChildNodes()) { Visit(child); } }
public override void DefaultVisit(SyntaxNode node) { foreach (var child in node.ChildNodes()) { child.Accept(this); } }
public override Token Get(SyntaxNode node) { var valueText = node .DescendantNodes() .OfType<IdentifierNameSyntax>() .Last() .Identifier.ValueText; if (valueText == null) { throw new NotImplementedException(); } var args = node.ChildNodes().OfType<ArgumentListSyntax>().First() .ChildNodes().OfType<ArgumentSyntax>().ToArray(); var whenClause = args[0].ChildNodes().First(); var block = args[1] .ChildNodes().OfType<ParenthesizedLambdaExpressionSyntax>().First() .ChildNodes().OfType<BlockSyntax>().First(); var details = new WhenClosureDetails(whenClause, block); return new Token("WhenClosure", details); }
private void Visit(SyntaxNode node, int spaces) { Console.WriteLine(new string(' ', spaces) + textVisitor.Visit(node)); foreach (var child in node.ChildNodes()) { Visit(child, spaces + 2); } }
public override Token Get(SyntaxNode node) { var argument = node .ChildNodes().OfType<ArgumentListSyntax>().First() .ChildNodes().OfType<ArgumentSyntax>().First(); var tokenDetails = GetDetails(argument); return new Token(Identifier(node).ToLower(), tokenDetails); }
public override void Visit(SyntaxNode node) { int padding = node.Ancestors().Count(); //To identify leaf nodes vs nodes with children string prepend = node.ChildNodes().Any() ? "[-]" : "[.]"; //Get the type of the node string line = new String(' ', padding) + prepend + " " + node.GetType().ToString(); //Write the line System.Console.WriteLine(line); base.Visit(node); }
protected override SyntaxNode GetTargetNode(SyntaxNode node) { if (node.IsKind(SyntaxKind.MemberBindingExpression)) { var nameNode = node.ChildNodes().FirstOrDefault(n => n.IsKind(SyntaxKind.IdentifierName)); if (nameNode != null) { return nameNode; } } return base.GetTargetNode(node); }
private SyntaxNode AddModifiers(SyntaxNode node, SyntaxToken syntaxToken) { // Get the first child node. SyntaxNode firstNode = node.ChildNodes().FirstOrDefault(); if (firstNode != null) { // The leading trivia will be the method comments, if any. SyntaxTriviaList leadingTrivia = firstNode.GetLeadingTrivia(); // Replace it with one without leading trivia. node = node.ReplaceNodes( new[] { firstNode }, (a, b) => firstNode.WithLeadingTrivia()); // Add the leading trivia to the new modifier. syntaxToken = syntaxToken.WithLeadingTrivia(leadingTrivia); } return node.AddModifiers(syntaxToken); }
protected void VisitChildren(SyntaxNode node) => VisitChildren(node.ChildNodes());
private IEnumerable <INamedTypeSymbol> GetNamespaceChildNodes <T>() where T : SyntaxNode { return(root.ChildNodes().OfType <NamespaceDeclarationSyntax>() .SelectMany(n => n.ChildNodes().OfType <T>()) .Select(c => semanticModel.GetDeclaredSymbol(c) as INamedTypeSymbol)); }
/// <summary> /// Statement are all segment separate by semi-colon. /// </summary> /// <param name="node"></param> /// <param name="state"></param> private VariableState VisitNode(SyntaxNode node, ExecutionState state) { //Logger.Log(node.GetType().ToString()); switch (node) { case LocalDeclarationStatementSyntax localDeclaration: return(VisitLocalDeclaration(localDeclaration, state)); case VariableDeclaratorSyntax variableDeclaration: return(VisitVariableDeclaration(variableDeclaration, state)); case AssignmentStatementSyntax assignment: return(VisitAssignmentStatement(assignment, state)); case ExpressionStatementSyntax expressionStatement: return(VisitExpressionStatement(expressionStatement, state)); case ExpressionSyntax expression: return(VisitExpression(expression, state)); case MethodBlockSyntax methodBlock: return(VisitMethodDeclaration(methodBlock, methodBlock.SubOrFunctionStatement.ParameterList, state)); case ConstructorBlockSyntax constructorBlockSyntax: return(VisitMethodDeclaration(constructorBlockSyntax, constructorBlockSyntax.SubNewStatement.ParameterList, state)); case PropertyBlockSyntax propertyBlockSyntax: { foreach (var accessor in propertyBlockSyntax.Accessors) { VisitBlock(accessor, state); } return(new VariableState(node, VariableTaint.Unknown)); } case ReturnStatementSyntax returnStatementSyntax: if (returnStatementSyntax.Expression == null) { return(new VariableState(node, VariableTaint.Unknown)); } return(VisitExpression(returnStatementSyntax.Expression, state)); case ForEachStatementSyntax forEachSyntax: return(VisitForEach(forEachSyntax, state)); } foreach (var n in node.ChildNodes()) { VisitNode(n, state); } var isBlockStatement = node is IfStatementSyntax || node is ForStatementSyntax; if (!isBlockStatement) { Logger.Log("Unsupported statement " + node.GetType() + " (" + node + ")"); } return(new VariableState(node, VariableTaint.Unknown)); }
public void Execute(GeneratorExecutionContext context) { if (context.SyntaxReceiver is not RecordSyntaxReceiver receiver) { throw new Exception(); } foreach (var recordDeclaration in receiver.RecordDeclarations) { context.CancellationToken.ThrowIfCancellationRequested(); if (recordDeclaration.ParameterList is null) { continue; } var semanticModel = context.Compilation.GetSemanticModel(recordDeclaration.SyntaxTree); var currLocation = recordDeclaration.GetLocation(); var currDeclaredSymbol = semanticModel.GetDeclaredSymbol(recordDeclaration); var canProcess = true; foreach (var location in currDeclaredSymbol!.Locations) { if (currLocation.SourceSpan.Contains(location.SourceSpan) || location.SourceSpan.Contains(currLocation.SourceSpan)) { continue; } var otherRecordDeclaration = location.SourceTree?.GetRoot() .DescendantNodesAndSelf() .OfType<RecordDeclarationSyntax>() .Where(syntax => SymbolEqualityComparer.Default.Equals( context.Compilation.GetSemanticModel(syntax.SyntaxTree).GetDeclaredSymbol(syntax), currDeclaredSymbol)) .ToArray() ?? Enumerable.Empty<RecordDeclarationSyntax>(); if (otherRecordDeclaration.Any(syntax => syntax.HasDefaultCtor())) { canProcess = false; break; } } if (!canProcess) { continue; } var recordName = recordDeclaration.Identifier.ToString(); SyntaxNode root = recordDeclaration; List<UsingDirectiveSyntax> usings = new(); List<string> wrappers = new(); while (root.Parent != null) { root = root.Parent; if (root is TypeDeclarationSyntax tds) { if (!tds.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword))) { throw new Exception("TADA"); // TODO } wrappers.Add($"{GetTypeDeclarationHeader(tds)}{Environment.NewLine}{{"); } if (root is NamespaceDeclarationSyntax namespaceDeclaration) { var @namespace = namespaceDeclaration.Name.ToString(); wrappers.Add($"namespace {@namespace}{Environment.NewLine}{{"); } usings.AddRange(root.ChildNodes().OfType<UsingDirectiveSyntax>()); } wrappers.Reverse(); // process parameters List<string> @params = new(); var syntaxNodes = recordDeclaration.ParameterList.ChildNodes().ToList(); foreach (var parameter in syntaxNodes.OfType<ParameterSyntax>()) { switch (parameter.Default?.Value) { case null: case DefaultExpressionSyntax: // check if type actually matches case LiteralExpressionSyntax lexs when lexs.IsKind(SyntaxKind.DefaultLiteralExpression): var typeSymbol = ModelExtensions.GetTypeInfo(semanticModel, parameter.Type!).Type; @params.Add($"default({typeSymbol})"); break; default: @params.Add(parameter.Default.Value.ToString()); break; } } var code = // @formatter:off @$" #pragma warning disable CS8019 {string.Join(Environment.NewLine + "\t", usings)} #pragma warning restore CS8019 {string.Join(Environment.NewLine + "\t", wrappers)} {GetTypeDeclarationHeader(recordDeclaration)} {{
private bool HasBlockChild(SyntaxNode node) { return node.ChildNodes().Any(n => n.Kind == SyntaxKind.Block); }
private SyntaxNode GetFirstBlockChild(SyntaxNode node) { return node.ChildNodes().First(n => n.Kind == SyntaxKind.Block); }
private static bool HasBody(SyntaxNode node) => node.ChildNodes().AnyOfKind(SyntaxKind.Block);
/// <summary> ///algorithm copied from /// http://stackoverflow.com/questions/1649027/how-do-i-print-out-a-tree-structure. /// </summary> /// <param name="node"></param> /// <param name="indent"></param> /// <param name="last"></param> /// <returns></returns> private string PrintPretty(SyntaxNode node,string indent, bool last) { var sb = new StringBuilder(); sb.Append(indent); if (last) { sb.Append("\\-"); indent += "\t"; } else { sb.Append("|-"); indent += "|\t"; } sb.AppendLine(node.Kind.ToString() + ":" + StringUtil.ReplaceNewLine(node.GetText(), "")); for (int i = 0; i < node.ChildNodes().Count() ; i++) { var child = node.ChildNodes().ElementAt(i); sb.Append(PrintPretty(child, indent, i == node.ChildNodes().Count() - 1)); } return sb.ToString(); }
/// <summary> /// Adds a new internal class with the given name equivalent to the passed type to the given syntax tree. /// /// Sets `created` to a reference to the newly created type. /// </summary> private static SyntaxNode AddType(NamedTypeSymbol equivTo, string withName, SyntaxNode tree, out TypeSyntax created) { created = Syntax.ParseTypeName(withName); var members = equivTo.GetMembers() .OfType<PropertySymbol>() .Select( s => { var prop = Syntax.PropertyDeclaration( null, Syntax.TokenList(Syntax.ParseToken("public")), Syntax.ParseTypeName(s.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)).WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")).WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), null, Syntax.Identifier(s.Name), Syntax.AccessorList( Syntax.List( Syntax.AccessorDeclaration( SyntaxKind.GetAccessorDeclaration, null, Syntax.TokenList(), Syntax.ParseToken("get"), null, Syntax.ParseToken(";") ), Syntax.AccessorDeclaration( SyntaxKind.SetAccessorDeclaration, null, Syntax.TokenList(), Syntax.ParseToken("set"), null, Syntax.ParseToken(";") ) ) ) ); return prop; } ) .Cast<MemberDeclarationSyntax>().ToList(); var separators = new List<SyntaxToken>(); for(var i = 0; i < members.Count - 1; i++) separators.Add(Syntax.ParseToken(",")); var obj = Syntax.AnonymousObjectCreationExpression( Syntax.SeparatedList( equivTo.GetMembers() .OfType<PropertySymbol>() .Select( p => { var exp = Syntax.IdentifierName(p.Name); return Syntax.AnonymousObjectMemberDeclarator(exp); } ), separators ) ).WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")); // Build the ToString() method that anonymous types have to have var toStringRef = Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, obj, Syntax.ParseToken("."), Syntax.IdentifierName("ToString")); var toStringAccess = Syntax.InvocationExpression(toStringRef); var toStringRet = Syntax.ReturnStatement(toStringAccess); var toStringStatements = Syntax.List<StatementSyntax>(toStringRet); var toStringBody = Syntax.Block( Syntax.ParseToken("{"), toStringStatements, Syntax.ParseToken("}") ); var toString = Syntax.MethodDeclaration( null, Syntax.TokenList(Syntax.ParseToken("public").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.ParseToken("override").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" "))), Syntax.ParseTypeName("string").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), null, Syntax.Identifier("ToString"), null, Syntax.ParameterList(), null, toStringBody ); members.Add(toString); // Adding GetHashCode override anonymous types must have var hashCodeRef = Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, obj, Syntax.ParseToken("."), Syntax.IdentifierName("GetHashCode")); var hashCodeAccess = Syntax.InvocationExpression(hashCodeRef); var hashCodeRet = Syntax.ReturnStatement(hashCodeAccess); var hashCodeStatements = Syntax.List<StatementSyntax>(hashCodeRet); var hashCodeBody = Syntax.Block( Syntax.ParseToken("{"), hashCodeStatements, Syntax.ParseToken("}") ); var hashCode = Syntax.MethodDeclaration( null, Syntax.TokenList(Syntax.ParseToken("public").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.ParseToken("override").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" "))), Syntax.ParseTypeName("int").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), null, Syntax.Identifier("GetHashCode"), null, Syntax.ParameterList(), null, hashCodeBody ); members.Add(hashCode); // Adding Equals method anonymous types must have var equalsAs = Syntax.ParseExpression("o as " + withName); var equalsAssign = Syntax.VariableDeclaration( created.WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.SeparatedList( Syntax.VariableDeclarator( Syntax.Identifier("other"), null, Syntax.EqualsValueClause(equalsAs) ) ) ); var equalsEqualsRef = Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, obj, Syntax.ParseToken("."), Syntax.IdentifierName("Equals")); var equalsAccess = Syntax.InvocationExpression(equalsEqualsRef, Syntax.ArgumentList(Syntax.SeparatedList(Syntax.Argument(Syntax.ParseExpression("o"))))); var equalsIf = Syntax.IfStatement( Syntax.ParseExpression("other == null"), Syntax.ReturnStatement(equalsAccess) ); var equalsEqualsExps = equivTo.GetMembers() .OfType<PropertySymbol>() .Select( p => { var n = p.Name; ExpressionSyntax ret; if (p.Type.IsReferenceType) { var strExp = "(" + n + " != null ? " + n + ".Equals(other." + n + ") : (other." + n + " != null ? other." + n + ".Equals(" + n + ") : true ))"; ret = Syntax.ParseExpression(strExp); } else { ret = Syntax.ParseExpression(n + " == other." + n); } return ret.WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")).WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")); } ).ToList(); ExpressionSyntax equalsBinary = equalsEqualsExps.First(); for (var i = 1; i < equalsEqualsExps.Count; i++) equalsBinary = Syntax.BinaryExpression(SyntaxKind.LogicalAndExpression, equalsBinary, equalsEqualsExps[i]); var equalsBinaryRet = Syntax.ReturnStatement(equalsBinary.WithLeadingTrivia(Syntax.ParseLeadingTrivia(" "))); var equalsStatements = Syntax.List( (StatementSyntax)Syntax.LocalDeclarationStatement(equalsAssign), (StatementSyntax)equalsIf, (StatementSyntax)equalsBinaryRet ); var equalsBody = Syntax.Block( Syntax.ParseToken("{"), equalsStatements, Syntax.ParseToken("}") ); var equals = Syntax.MethodDeclaration( null, Syntax.TokenList(Syntax.ParseToken("public").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.ParseToken("override").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" "))), Syntax.ParseTypeName("bool").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), null, Syntax.Identifier("Equals"), null, Syntax.ParameterList( Syntax.SeparatedList( Syntax.Parameter( null, Syntax.TokenList(), Syntax.ParseTypeName("object").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.Identifier("o"), null ) ) ), null, equalsBody ); members.Add(equals); var equiv = Syntax.ClassDeclaration( null, Syntax.ParseToken("internal").WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), Syntax.Identifier(withName).WithLeadingTrivia(Syntax.ParseLeadingTrivia(" ")).WithTrailingTrivia(Syntax.ParseTrailingTrivia(" ")), null, null, null, Syntax.List<MemberDeclarationSyntax>(members) ); var namespaces = tree.ChildNodes().OfType<NamespaceDeclarationSyntax>(); if (namespaces.Count() == 0 || namespaces.Count() > 1) { // HACK, better way to insert classes should be considered throw new Exception("Making some assumptions about namespaces, you can only have 1"); } var @namespace = namespaces.Single(); var updated = @namespace.WithMembers( @namespace.Members.Add(equiv) ); return tree.ReplaceNode(@namespace, updated); }
private static bool TryGetChildTypeNode(SyntaxNode node, out SyntaxNode childTypeNode) { childTypeNode = node.ChildNodes().Where(x => x.IsKind(SyntaxKind.IdentifierName) || x.IsKind(SyntaxKind.PredefinedType) || x.IsKind(SyntaxKind.GenericName) || x.IsKind(SyntaxKind.ArrayType) || x.IsKind(SyntaxKind.TupleType)).FirstOrDefault(); return(childTypeNode != null); }
private void LogSyntaxTree(SyntaxNode node, StringBuilder builder, int ident = 0, bool skipSelf = false) { string sident = String.Empty; for (int i = 0; i < ident; ++i) sident += "\t"; if (!skipSelf) { builder.AppendLine (sident + node.GetType() + ": " + node); ident++; } foreach (SyntaxNode childNode in node.ChildNodes()) LogSyntaxTree (childNode, builder, ident); }
/// <summary> /// Statement are all segment separate by semi-colon. /// </summary> /// <param name="node"></param> /// <param name="state"></param> private VariableState VisitNode(SyntaxNode node, ExecutionState state) { //Logger.Log(node.GetType().ToString()); switch (node) { case LocalDeclarationStatementSyntax declarationStatementSyntax: return(VisitLocalDeclaration(declarationStatementSyntax, state)); case VariableDeclarationSyntax variableDeclarationSyntax: return(VisitVariableDeclaration(variableDeclarationSyntax, state)); case ExpressionStatementSyntax expressionStatementSyntax: return(VisitExpressionStatement(expressionStatementSyntax, state)); case ExpressionSyntax expressionSyntax: return(VisitExpression(expressionSyntax, state)); case MethodDeclarationSyntax methodDeclarationSyntax: return(VisitMethodDeclaration(methodDeclarationSyntax, state)); case ConstructorDeclarationSyntax constructorDeclarationSyntax: return(VisitMethodDeclaration(constructorDeclarationSyntax, state)); case DestructorDeclarationSyntax destructorDeclarationSyntax: return(VisitMethodDeclaration(destructorDeclarationSyntax, state)); case PropertyDeclarationSyntax propertyDeclarationSyntax: { if (propertyDeclarationSyntax.ExpressionBody != null) { return(VisitNode(propertyDeclarationSyntax.ExpressionBody, state)); } foreach (var accessor in propertyDeclarationSyntax.AccessorList.Accessors) { if (accessor.Body != null) { VisitBlock(accessor.Body, state); } } return(new VariableState(node, VariableTaint.Unknown)); } case ReturnStatementSyntax returnStatementSyntax: if (returnStatementSyntax.Expression == null) { return(new VariableState(node, VariableTaint.Unknown)); } return(VisitExpression(returnStatementSyntax.Expression, state)); case ForEachStatementSyntax forEachSyntax: return(VisitForEach(forEachSyntax, state)); case BlockSyntax blockSyntax: return(VisitBlock(blockSyntax, state)); } foreach (var n in node.ChildNodes()) { VisitNode(n, state); } var isBlockStatement = node is IfStatementSyntax || node is ForStatementSyntax; if (!isBlockStatement) { Logger.Log("Unsupported statement " + node.GetType() + " (" + node + ")"); } return(new VariableState(node, VariableTaint.Unknown)); }