public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { if (methodImpl is null) { return(node); } if (semanticModel.GetDeclaredSymbol(node) is not IMethodSymbol m) { return(node); } if (m.MethodKind == MethodKind.Ordinary || m.MethodKind == MethodKind.ExplicitInterfaceImplementation) { if (m.GetAttributes() .Select(at => at.AttributeClass) .Contains(methodImpl, SymbolEqualityComparer.Default)) { return(node); } return(node.AddAttributeLists(SyntaxHelpers.AggressiveInliningAttributeList)); } return(node); }
/// <summary> /// Creates a <see cref="CompilationUnitSyntax"/> instance wrapping the given method. /// </summary> /// <param name="hierarchyInfo">The <see cref="HierarchyInfo"/> instance for the current type.</param> /// <param name="methodDeclaration">The <see cref="MethodDeclarationSyntax"/> item to insert.</param> /// <param name="canUseSkipLocalsInit">Whether <c>[SkipLocalsInit]</c> can be used.</param> /// <returns>A <see cref="CompilationUnitSyntax"/> object wrapping <paramref name="methodDeclaration"/>.</returns> private static CompilationUnitSyntax GetCompilationUnitFromMethod( HierarchyInfo hierarchyInfo, MethodDeclarationSyntax methodDeclaration, bool canUseSkipLocalsInit) { // Method attributes List <AttributeListSyntax> attributes = new() { AttributeList(SingletonSeparatedList( Attribute(IdentifierName("global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments( AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ID2D1ShaderGenerator).FullName))), AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(ID2D1ShaderGenerator).Assembly.GetName().Version.ToString())))))), AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))), AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))), AttributeList(SingletonSeparatedList( Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments( AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))), AttributeList(SingletonSeparatedList( Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments( AttributeArgument(LiteralExpression( SyntaxKind.StringLiteralExpression, Literal("This method is not intended to be used directly by user code")))))) }; // Add [SkipLocalsInit] if the target project allows it if (canUseSkipLocalsInit) { attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Runtime.CompilerServices.SkipLocalsInit"))))); } return(hierarchyInfo.GetSyntax(methodDeclaration.AddAttributeLists(attributes.ToArray()))); } }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) { var originalName = node.Identifier.ValueText; var name = originalName; HandleArchSpecific(node, out var removeNode, out var attributeList, ref name); if (removeNode) { return(null); } if (name != originalName) { node = node.WithIdentifier(SyntaxFactory.ParseToken(name)); } if (attributeList != null) { node = node.AddAttributeLists(attributeList); } } return(node); }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); if (!node.Modifiers.Any(x => x.ValueText == "public")) { return(node); } if ((node.ReturnType as PredefinedTypeSyntax)?.Keyword.ValueText != "void" && !(node.Modifiers.Any(x => x.ValueText == "async") && node.ReturnType.ToFullString().Contains("Task"))) { return(node); } if (node.ParameterList.Parameters.Any()) { return(node); } if (node.AttributeLists.SelectMany(x => x.Attributes).Any()) { return(node); } return(node.AddAttributeLists(new AttributeListSyntax[] { SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("Test")))) })); }
private async Task <Solution> AddThrowsAttributeAsync(Document document, MethodDeclarationSyntax methodDecl, SyntaxToken diagnosticSpan, CancellationToken cancellationToken) { var semModel = await document.GetSemanticModelAsync(); var syntaxRoot = await document.GetSyntaxRootAsync(); var exceptionType = diagnosticSpan .Parent .AncestorsAndSelf() .Select(x => semModel.GetTypeInfo(x)) .FirstOrDefault(x => x.Type != null); ITypeSymbol exceptionSymbol = exceptionType.Type; bool hasUsing = syntaxRoot.DescendantNodes().OfType <UsingDirectiveSyntax>() .Any(u => u.Name.ToString() == ThrowsAttributeNamespace); var newMethodDecl = methodDecl.AddAttributeLists( SyntaxFactory.AttributeList( SyntaxFactory.SingletonSeparatedList( CreateThrowsAttribute(await document.GetSemanticModelAsync(), methodDecl, exceptionSymbol, !hasUsing) ) ) ).WithoutLeadingTrivia(); return(document.WithSyntaxRoot( syntaxRoot.ReplaceNode(methodDecl, newMethodDecl) ).Project.Solution); }
private static SyntaxNode AddAttribute(SyntaxNode root, MethodDeclarationSyntax methodNode, string name) { var attribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName(name)); var attributeList = SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList <AttributeSyntax>().Add(attribute)); var newClassNode = methodNode.AddAttributeLists(attributeList); return(root.ReplaceNode(methodNode, newClassNode)); }
public static MethodDeclarationSyntax CreateMethod(MethodGenerationData data) { Debug.Assert(!string.IsNullOrEmpty(data.m_MethodName), "Trying to generate a method with null or empty method name!"); Debug.Assert(!string.IsNullOrEmpty(data.m_MethodReturnType), "Trying to generate a method with null or empty return type!"); Debug.Assert(data.m_MethodBodyStatements != null && data.m_MethodBodyStatements.Count > 0, "Trying to generate a method with no body!"); MethodDeclarationSyntax syntax = SyntaxFactory .MethodDeclaration(SyntaxFactory.ParseTypeName(data.m_MethodReturnType), data.m_MethodName) .AddModifiers(CodeGenerationUtility.CreateProtectionLevelToken(data.m_ProtectionLevel)); switch (data.m_InheritanceKeyword) { case FunctionInheritanceKeyword.STATIC: syntax = syntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.StaticKeyword)); break; case FunctionInheritanceKeyword.OVERRIDE: syntax = syntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.OverrideKeyword)); break; case FunctionInheritanceKeyword.VIRTUAL: syntax = syntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.VirtualKeyword)); break; } if (data.m_IsAsync) { bool canMakeAsync = false; for (int i = 0; i < s_AcceptedAsyncReturnTypes.Length; i++) { if (!data.m_MethodReturnType.Contains(s_AcceptedAsyncReturnTypes[i])) { continue; } canMakeAsync = true; break; } Debug.Assert(canMakeAsync, "Trying to generate async function but the return type is not supported! Please make the return type either void, Task or UniTask"); if (canMakeAsync) { syntax = syntax.AddModifiers(SyntaxFactory.Token(SyntaxKind.AsyncKeyword)); } } syntax = syntax.AddAttributeLists(AttributeGenerationService.CreateAttributeListSyntaxes(data.m_Attributes)); foreach (var param in data.m_MethodParams) { syntax = syntax.AddParameterListParameters(CodeGenerationUtility.CreateParameterSyntax(param.m_ParamName, param.m_ParamType)); } foreach (var statement in data.m_MethodBodyStatements) { syntax = syntax.AddBodyStatements((SyntaxFactory.ParseStatement(statement))); } return(syntax); }
private static async Task <Document> AddNewAttribute(Document document, MethodDeclarationSyntax methodDeclaration, NameSyntax qualifiedName, CancellationToken cancellationToken) { var newAttribute = SyntaxFactory.Attribute(qualifiedName); var newAttributeList = SyntaxFactory.AttributeList().AddAttributes(newAttribute).WithAdditionalAnnotations(Formatter.Annotation); var newDeclaration = methodDeclaration.AddAttributeLists(newAttributeList); var oldRoot = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = oldRoot !.ReplaceNode(methodDeclaration, newDeclaration); return(document.WithSyntaxRoot(newRoot)); }
public static MethodDeclarationSyntax AddNeo4JDatabaseAttribute( this MethodDeclarationSyntax methodSyntax, string databaseName) { AttributeSyntax attribute = Attribute(IdentifierName(Global(UseNeo4JDatabaseAttribute))) .AddArgumentListArguments( AttributeArgument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(databaseName))) .WithNameColon( NameColon(IdentifierName(nameof(databaseName))))); return(methodSyntax.AddAttributeLists(AttributeList(SingletonSeparatedList(attribute)))); }
private MethodDeclarationSyntax FixAsyncFunctionMethod(MethodDeclarationSyntax targetMethod, CancellationToken cancellationToken) { MethodDeclarationSyntax updatedmethod = targetMethod; var name = SyntaxFactory.ParseName("NetStitch.Operation"); var attribute = SyntaxFactory.Attribute(name); var attributeList = new SeparatedSyntaxList <AttributeSyntax>(); attributeList = attributeList.Add(attribute); var list = SyntaxFactory.AttributeList(attributeList); updatedmethod = updatedmethod.AddAttributeLists(list); if (updatedmethod.Identifier.Text.IsAsyncSuffixTarget()) { updatedmethod = updatedmethod.ReplaceToken(updatedmethod.Identifier, SyntaxFactory.Identifier(updatedmethod.Identifier + "Async")); } if (updatedmethod.ParameterList.Parameters.Count == 0) { /* * #if !___server___ * System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken) * #endif */ updatedmethod = updatedmethod.AddParameterListParameters( SyntaxFactory.Parameter( SyntaxFactory.Identifier("cancellationToken") .WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) .WithTrailingTrivia(SyntaxFactory.Whitespace(" ")) ) .WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) .WithType( SyntaxFactory.ParseTypeName(typeof(CancellationToken).FullName)) .WithLeadingTrivia(SyntaxFactory.Whitespace(" " + " ")) .WithDefault( SyntaxFactory.EqualsValueClause( SyntaxFactory.DefaultExpression( SyntaxFactory.ParseTypeName(typeof(CancellationToken).FullName) ) .WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) ) ) .WithLeadingTrivia( SyntaxFactory.Trivia(SyntaxFactory.IfDirectiveTrivia(SyntaxFactory.IdentifierName("!___server___"), false, false, false)), SyntaxFactory.EndOfLine("\r\n"), SyntaxFactory.Whitespace(" " + " ") ) .WithTrailingTrivia( SyntaxFactory.EndOfLine("\r\n"), SyntaxFactory.Trivia( SyntaxFactory.EndIfDirectiveTrivia(false) .WithTrailingTrivia( SyntaxFactory.EndOfLine("\r\n"), SyntaxFactory.Whitespace(" " + " ") )) )); } else { /* * #if !___server___ * , System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken) * #endif */ updatedmethod = updatedmethod.AddParameterListParameters( SyntaxFactory.Parameter( SyntaxFactory.Identifier("cancellationToken") .WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) .WithTrailingTrivia(SyntaxFactory.Whitespace(" ")) ) .WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) .WithType( SyntaxFactory.ParseTypeName(typeof(CancellationToken).FullName)) .WithLeadingTrivia(SyntaxFactory.Whitespace(" " + " ")) .WithDefault( SyntaxFactory.EqualsValueClause( SyntaxFactory.DefaultExpression( SyntaxFactory.ParseTypeName(typeof(CancellationToken).FullName) ) .WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) ) ) .WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) .WithTrailingTrivia( SyntaxFactory.EndOfLine("\r\n"), SyntaxFactory.Trivia( SyntaxFactory.EndIfDirectiveTrivia(false) .WithTrailingTrivia( SyntaxFactory.EndOfLine("\r\n"), SyntaxFactory.Whitespace(" " + " ") )) )); var commaToken = updatedmethod.ParameterList.ChildTokens().Where(x => x.IsKind(SyntaxKind.CommaToken)).Last(); var newToken = commaToken.WithLeadingTrivia( SyntaxFactory.Whitespace("\r\n"), SyntaxFactory.Trivia(SyntaxFactory.IfDirectiveTrivia(SyntaxFactory.IdentifierName("!___server___"), false, false, false)), SyntaxFactory.EndOfLine("\r\n"), SyntaxFactory.Whitespace(" " + " ") ); var newParameterList = updatedmethod.ParameterList.ReplaceToken(commaToken, newToken); updatedmethod = updatedmethod.ReplaceNode(updatedmethod.ParameterList, newParameterList); } return(updatedmethod); }
public static MethodDeclarationSyntax WithAttributes(this MethodDeclarationSyntax node, params AttributeSyntax[] attributes) { return(node.AddAttributeLists(AttributeList(SeparatedList(attributes)))); }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { if (methodImplAttribute is null) { return(node); } if (methodImplOptions is null) { return(node); } if (semanticModel.GetDeclaredSymbol(node) is not IMethodSymbol m) { return(node); } if (m.MethodKind is not(MethodKind.ExplicitInterfaceImplementation or MethodKind.Ordinary)) { return(node); } if (m.GetAttributes() .FirstOrDefault(at => SymbolEqualityComparer.Default.Equals(at.AttributeClass, methodImplAttribute)) is not { } attr || attr.ApplicationSyntaxReference?.GetSyntax() is not AttributeSyntax syntax) { return(node.AddAttributeLists(AttributeList(SingletonSeparatedList(aggressiveInliningAttribute)))); } if (attr.ConstructorArguments.Length > 0) { var arg = attr.ConstructorArguments[0]; if (arg.Kind is TypedConstantKind.Primitive or TypedConstantKind.Enum) { try { if (((MethodImplOptions)Convert.ToInt32(arg.Value)).HasFlag(MethodImplOptions.AggressiveInlining)) { return(node); } } catch { } } } var list = new List <AttributeListSyntax>(node.AttributeLists.Count); foreach (var attributeList in node.AttributeLists) { if (attributeList.Attributes.Contains(syntax)) { var replaced = attributeList.Attributes.Replace(syntax, AddAggressiveInlining(syntax, attr)); list.Add(AttributeList(replaced)); } else { list.Add(attributeList); } } return(node.WithAttributeLists(new SyntaxList <AttributeListSyntax>(list))); }
private MethodDeclarationSyntax ProcessTestMethod(MethodDeclarationSyntax node) { // Replace protected keyword with public SyntaxToken replaceToPublic(SyntaxToken token) { if (token.IsKind(SyntaxKind.ProtectedKeyword)) { token = SyntaxFactory.Token(token.LeadingTrivia, SyntaxKind.PublicKeyword, token.TrailingTrivia); } return(token); } var modifiers = node.Modifiers.Select(replaceToPublic); node = node.WithModifiers(new SyntaxTokenList(modifiers)); // Replace method name with Component_Type_Methodname var methodName = node.ChildTokens().First((x) => x.IsKind(SyntaxKind.IdentifierToken)); var testTypeName = testType.ToString("G").Substring(0, 1).ToUpperInvariant() + "_"; var componentName = GetComponentName(node); var shortComponentName = string.IsNullOrEmpty(componentName) ? componentName : componentName.Substring(0, 2).ToUpperInvariant() + "_"; var newMethodName = SyntaxFactory.Identifier(methodName.LeadingTrivia, $"{shortComponentName}{testTypeName}{methodName.ValueText}", methodName.TrailingTrivia); node = node.ReplaceToken(methodName, newMethodName); // Call original method instead of logic var isAsyncMethod = node.Modifiers.Any((x) => x.IsKind(SyntaxKind.AsyncKeyword)); // hack for proper indentation: margin-to-method indentation + 1/2 var indentTrivia = node.QueryNodesOrTokensAtPath(SyntaxKind.Block, SyntaxKind.OpenBraceToken).First().GetLeadingTrivia().First(); var indentTriviaHalf = SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, new string(' ', indentTrivia.ToString().Length / 2)); ExpressionStatementSyntax body; if (isAsyncMethod) { body = SyntaxFactory.ExpressionStatement( SyntaxFactory.AwaitExpression( SyntaxFactory.Token(new SyntaxTriviaList(indentTrivia, indentTriviaHalf), SyntaxKind.AwaitKeyword, TestHelper.Space.AsList()), SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName(methodName.ValueText)) ), TestHelper.Semicolon ); } else { body = SyntaxFactory.ExpressionStatement( SyntaxFactory.InvocationExpression( SyntaxFactory.IdentifierName( SyntaxFactory.Identifier( new SyntaxTriviaList(indentTrivia, indentTriviaHalf), methodName.ValueText, TestHelper.Empty.AsList() ) ) ), TestHelper.Semicolon ); } var bodyList = new SyntaxList <StatementSyntax>(body); Debug.Assert(indentTrivia.IsKind(SyntaxKind.WhitespaceTrivia)); var openBrace = SyntaxFactory.Token(indentTrivia.AsList(), SyntaxKind.OpenBraceToken, TestHelper.NewLine.AsList()); var closeBrace = SyntaxFactory.Token(indentTrivia.AsList(), SyntaxKind.CloseBraceToken, TestHelper.NewLine.AsList()); node = node.WithBody(SyntaxFactory.Block(openBrace, bodyList, closeBrace)); // Export TestType arguments and decorate the method with them individually var arguments = GetTestTypeArguments(node); MethodDeclarationSyntax createNewAttribute(string attributeName) { return(node.AddAttributeLists( SyntaxFactory.AttributeList( SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Attribute( SyntaxFactory.IdentifierName(attributeName) ) } ) ) .WithTrailingTrivia(node.AttributeLists.First().GetTrailingTrivia()) .WithLeadingTrivia(indentTrivia) )); } if (arguments.SmokeTest) { node = createNewAttribute("SmokeTest"); } if (arguments.Devel) { node = createNewAttribute("DevelTest"); } if (arguments.Production) { node = createNewAttribute("ProductionTest"); } if (!string.IsNullOrEmpty(componentName)) { node = createNewAttribute(componentName + "Component"); } // Remove unused attributes var removableAttrLists = node.AttributeLists.Where((attribList) => attribList.Attributes.Any((attrib) => { var testTypes = new[] { "TestComponent", "InMemoryTest", "LocalTest", "RemoteTest" }.ToList(); var attributeName = attrib.Name.GetText().ToString(); return(testTypes.Contains(attributeName)); })); node = node.RemoveNodes(removableAttrLists, SyntaxRemoveOptions.KeepNoTrivia); return(node); }
public static MethodDeclarationSyntax WithNonActionAttribute(this MethodDeclarationSyntax node) => node.AddAttributeLists(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("NonAction")))));
public static MethodDeclarationSyntax WithGeneratedNonUserCodeAttributes(this MethodDeclarationSyntax node) => node.AddAttributeLists(GeneratedNonUserCodeAttributeList());
public static MethodDeclarationSyntax AddAttributeLists(this MethodDeclarationSyntax syntax, IEnumerable <AttributeListSyntax> lists) { return(syntax.AddAttributeLists(lists.ToArray())); }
/// <summary> /// Creates a <see cref="CompilationUnitSyntax"/> instance wrapping the given method. /// </summary> /// <param name="hierarchyInfo">The <see cref="HierarchyInfo"/> instance for the current type.</param> /// <param name="methodDeclaration">The <see cref="MethodDeclarationSyntax"/> item to insert.</param> /// <param name="canUseSkipLocalsInit">Whether <c>[SkipLocalsInit]</c> can be used.</param> /// <returns>A <see cref="CompilationUnitSyntax"/> object wrapping <paramref name="methodDeclaration"/>.</returns> private static CompilationUnitSyntax GetCompilationUnitFromMethod( HierarchyInfo hierarchyInfo, MethodDeclarationSyntax methodDeclaration, bool canUseSkipLocalsInit) { // Method attributes List <AttributeListSyntax> attributes = new() { AttributeList(SingletonSeparatedList( Attribute(IdentifierName("global::System.CodeDom.Compiler.GeneratedCode")).AddArgumentListArguments( AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IShaderGenerator).FullName))), AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(typeof(IShaderGenerator).Assembly.GetName().Version.ToString())))))), AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.DebuggerNonUserCode")))), AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage")))), AttributeList(SingletonSeparatedList( Attribute(IdentifierName("global::System.ComponentModel.EditorBrowsable")).AddArgumentListArguments( AttributeArgument(ParseExpression("global::System.ComponentModel.EditorBrowsableState.Never"))))), AttributeList(SingletonSeparatedList( Attribute(IdentifierName("global::System.Obsolete")).AddArgumentListArguments( AttributeArgument(LiteralExpression( SyntaxKind.StringLiteralExpression, Literal("This method is not intended to be used directly by user code")))))) }; // Add [SkipLocalsInit] if the target project allows it if (canUseSkipLocalsInit) { attributes.Add(AttributeList(SingletonSeparatedList(Attribute(IdentifierName("global::System.Runtime.CompilerServices.SkipLocalsInit"))))); } // Create the partial shader type declaration with the given method implementation. // This code produces a struct declaration as follows: // // partial struct <SHADER_TYPE> // { // <METHOD> // } StructDeclarationSyntax structDeclarationSyntax = StructDeclaration(hierarchyInfo.Names[0]) .AddModifiers(Token(SyntaxKind.PartialKeyword)) .AddMembers(methodDeclaration.AddAttributeLists(attributes.ToArray())); TypeDeclarationSyntax typeDeclarationSyntax = structDeclarationSyntax; // Add all parent types in ascending order, if any foreach (string parentType in hierarchyInfo.Names.AsSpan().Slice(1)) { typeDeclarationSyntax = ClassDeclaration(parentType) .AddModifiers(Token(SyntaxKind.PartialKeyword)) .AddMembers(typeDeclarationSyntax); } // Create the compilation unit with disabled warnings, target namespace and generated type. // This will produce code as follows: // // #pragma warning disable // // namespace <NAMESPACE>; // // <TYPE_HIERARCHY> return (CompilationUnit().AddMembers( FileScopedNamespaceDeclaration(IdentifierName(hierarchyInfo.Namespace)) .AddMembers(typeDeclarationSyntax) .WithNamespaceKeyword(Token(TriviaList( Trivia(PragmaWarningDirectiveTrivia(Token(SyntaxKind.DisableKeyword), true))), SyntaxKind.NamespaceKeyword, TriviaList()))) .NormalizeWhitespace(eol: "\n")); } }