public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) { node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node); MethodDeclarationSyntax prector = Syntax.MethodDeclaration(Syntax.PredefinedType(Syntax.Token(SyntaxKind.VoidKeyword)), ".prector"); List<StatementSyntax> Initializers = new List<StatementSyntax>(); foreach (MemberDeclarationSyntax member in node.Members) { if (member.Kind == SyntaxKind.FieldDeclaration) { FieldDeclarationSyntax fds = (FieldDeclarationSyntax)member; foreach (VariableDeclaratorSyntax vds in fds.Declaration.Variables) { if (vds.Initializer != null) { Initializers.Add(Syntax.ExpressionStatement(Syntax.BinaryExpression(SyntaxKind.AssignExpression, Syntax.IdentifierName(vds.Identifier), vds.Initializer.Value))); } } } } if (Initializers.Count == 0) return node; int constructors = node.Members.Count((m) => (m is ConstructorDeclarationSyntax)); prector = prector.AddBodyStatements(Initializers.ToArray()); node = node.AddMembers(prector); if (constructors == 0) { ConstructorDeclarationSyntax ctor = Syntax.ConstructorDeclaration(node.Identifier); ctor = ctor.AddBodyStatements(Syntax.ExpressionStatement(Syntax.InvocationExpression(Syntax.IdentifierName(".prector")))); ctor = ctor.AddModifiers(Syntax.Token(SyntaxKind.PublicKeyword)); return node.AddMembers(ctor); } SyntaxList<MemberDeclarationSyntax> newMembers = new SyntaxList<MemberDeclarationSyntax>(); foreach (MemberDeclarationSyntax member in node.Members) { if (member.Kind == SyntaxKind.ConstructorDeclaration) { newMembers = newMembers.Add((MemberDeclarationSyntax)ConstructorPrefixerDeclaration((ConstructorDeclarationSyntax)member)); } else { newMembers = newMembers.Add(member); } } return node.WithMembers(newMembers); }
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) { node = (ClassDeclarationSyntax)base.VisitClassDeclaration(node); SyntaxList<MemberDeclarationSyntax> newMembers = new SyntaxList<MemberDeclarationSyntax>(); foreach (MemberDeclarationSyntax member in node.Members) { if (member.Kind == SyntaxKind.PropertyDeclaration) { PropertyDeclarationSyntax prop = (PropertyDeclarationSyntax)member; SyntaxList<AccessorDeclarationSyntax> newAccessors = new SyntaxList<AccessorDeclarationSyntax>(); bool implementfield = false; foreach (AccessorDeclarationSyntax accessor in prop.AccessorList.Accessors) { if (accessor.Body == null) { switch (accessor.Kind) { case SyntaxKind.GetAccessorDeclaration: implementfield = true; newAccessors = newAccessors.Add(accessor.WithBody(Syntax.Block(Syntax.ReturnStatement(Syntax.IdentifierName("_" + prop.Identifier.ValueText))))); break; case SyntaxKind.SetAccessorDeclaration: implementfield = true; newAccessors = newAccessors.Add(accessor.WithBody(Syntax.Block(Syntax.ExpressionStatement(Syntax.BinaryExpression(SyntaxKind.AssignExpression, Syntax.IdentifierName("_" + prop.Identifier.ValueText), Syntax.IdentifierName("value")))))); break; default: newAccessors = newAccessors.Add(accessor); break; } } else { newAccessors = newAccessors.Add(accessor); } } if (implementfield) { SeparatedSyntaxList<VariableDeclaratorSyntax> variables = new SeparatedSyntaxList<VariableDeclaratorSyntax>(); variables = variables.Add(Syntax.VariableDeclarator("_" + prop.Identifier.ValueText)); newMembers = newMembers.Add(Syntax.FieldDeclaration(Syntax.VariableDeclaration(prop.Type, variables))); } newMembers = newMembers.Add(prop.WithAccessorList(prop.AccessorList.WithAccessors(newAccessors))); } else { newMembers = newMembers.Add(member); } } return node.WithMembers(newMembers); }
public CodeActionEdit GetEdit(CancellationToken cancellationToken = new CancellationToken()) { var newReturnType = Syntax.ParseTypeName("HttpResponseMessage").WithTrailingTrivia(Syntax.Space); var exp = Syntax.ParseExpression("new HttpResponseMessage(HttpStatusCode.Created)").WithLeadingTrivia(Syntax.Space); var returnStatement = Syntax.ReturnStatement(Syntax.Token(SyntaxKind.ReturnKeyword), exp ,Syntax.Token(SyntaxKind.SemicolonToken)); var oldBody = _method.Body; var statements = oldBody.Statements.Where(x => x.GetType() != typeof (ReturnStatementSyntax)).ToList(); var syntaxListStatements = new SyntaxList<StatementSyntax>(); syntaxListStatements = statements.Aggregate(syntaxListStatements, (current, syntaxListStatement) => current.Add(syntaxListStatement)); syntaxListStatements = syntaxListStatements.Add(returnStatement); var newBody = Syntax.Block(Syntax.Token(SyntaxKind.OpenBraceToken), syntaxListStatements, Syntax.Token(SyntaxKind.CloseBraceToken)); var newmethod = Syntax.MethodDeclaration(_method.AttributeLists, _method.Modifiers, newReturnType, _method.ExplicitInterfaceSpecifier, _method.Identifier, _method.TypeParameterList, _method.ParameterList, _method.ConstraintClauses, newBody); var oldRoot = _document.GetSyntaxRoot(cancellationToken); var newRoot = oldRoot.ReplaceNode(_method,newmethod); var newDoc = _document.UpdateSyntaxRoot(newRoot.Format(FormattingOptions.GetDefaultOptions()).GetFormattedRoot()); return new CodeActionEdit(newDoc); }
/// <summary> /// Create the public instance methods. /// </summary> /// <param name="members">The structure members.</param> /// <returns>The structure members with the methods added.</returns> private SyntaxList <MemberDeclarationSyntax> CreatePublicInstanceMethods(SyntaxList <MemberDeclarationSyntax> members) { // This will create the public instance properties. List <SyntaxElement> methods = new List <SyntaxElement>(); // Generate support for the HTTP verbs. methods.Add(new DeleteOneMethod(this.tableElement)); methods.Add(new DeleteMethod(this.tableElement)); methods.Add(new GetAllMethod(this.tableElement)); methods.Add(new GetMethod(this.tableElement.PrimaryKey)); methods.Add(new PostMethod(this.tableElement)); methods.Add(new PutMethod(this.tableElement)); methods.Add(new PatchMethod(this.tableElement)); // Alphabetize and add the methods as members of the class. foreach (SyntaxElement syntaxElement in methods.OrderBy(m => m.Name)) { members = members.Add(syntaxElement.Syntax); } // Return the new collection of members. return(members); }
private async Task <Document> RemoveDescriptionAttribute(Document document, MethodDeclarationSyntax method, CancellationToken cancellationToken) { SyntaxNode rootNode = await document.GetSyntaxRootAsync(cancellationToken); var newAttributes = new SyntaxList <AttributeListSyntax>(); foreach (AttributeListSyntax attributelist in method.AttributeLists) { var nodesToRemove = attributelist.Attributes.Where(att => (att.Name as IdentifierNameSyntax).Identifier.Text.StartsWith("Description")).ToArray(); if (nodesToRemove.Length != attributelist.Attributes.Count) { var newAttribute = (AttributeListSyntax)attributelist.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia); newAttributes = newAttributes.Add(newAttribute); } } MethodDeclarationSyntax newMethod = method.WithAttributeLists(newAttributes); SyntaxNode newRoot = rootNode.ReplaceNode(method, newMethod); Document newDocument = document.WithSyntaxRoot(newRoot); return(newDocument); }
public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) { if (node.AttributeLists.Count > 0) { var newAttributeLists = new SyntaxList <AttributeListSyntax>(); foreach (var attributeList in node.AttributeLists) { var nodesToRemove = attributeList.Attributes.Where(attribute => NodeHelper.AttributeNameMatches(attribute, Constants.Proto.BASE_PROP_NAME)).ToArray(); // If the lists are the same length, we are removing all attributes and can just avoid populating newAttributes. if (nodesToRemove.Length != attributeList.Attributes.Count) { var newAttribute = (AttributeListSyntax)VisitAttributeList(attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia)); newAttributeLists = newAttributeLists.Add(newAttribute); } } var leadTriv = node.GetLeadingTrivia(); node = node.WithAttributeLists(newAttributeLists); node = node.WithLeadingTrivia(leadTriv); } return(base.VisitPropertyDeclaration(node)); }
/// <summary> /// Create the private instance fields. /// </summary> /// <param name="members">The structure members.</param> /// <returns>The syntax for creating the internal instance properties.</returns> private SyntaxList <MemberDeclarationSyntax> CreatePrivateInstanceFields(SyntaxList <MemberDeclarationSyntax> members) { // This will create the private instance fields. List <SyntaxElement> fields = new List <SyntaxElement>(); fields.Add(new CurrentDataField()); fields.Add(new PreviousDataField()); fields.Add(new RecordCollectionField(this.tableElement)); // Create these fields for each child table. foreach (ForeignKeyElement foreignKeyElement in this.tableElement.ChildKeys) { fields.Add(new GetChildrenFunctionField(foreignKeyElement)); } // Alphabetize and add the fields as members of the class. foreach (SyntaxElement syntaxElement in fields.OrderBy(m => m.Name)) { members = members.Add(syntaxElement.Syntax); } // Return the new collection of members. return(members); }
private SyntaxList <AttributeListSyntax> RemoveAttribute(string attributeName, SyntaxList <AttributeListSyntax> attributeLists) { var changedAttributeLists = new SyntaxList <AttributeListSyntax>(); foreach (var attributeList in attributeLists) { var nodesToRemove = attributeList .Attributes .Where(a => GetSimpleNameFromNode(a).Identifier.ValueText == attributeName) .ToArray(); // If the lists are the same length, we are removing all attributes and can just avoid populating newAttributes if (nodesToRemove.Length != attributeList.Attributes.Count) { var newAttributeList = (AttributeListSyntax)VisitAttributeList( attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia)); changedAttributeLists = changedAttributeLists.Add(newAttributeList); } } return(changedAttributeLists); }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { var newAttributes = new SyntaxList <AttributeListSyntax>(); foreach (var attributeList in node.AttributeLists) { var nodesToRemove = attributeList .Attributes .Where( attribute => AttributeNameMatches(attribute) && HasMatchingAttributeValue(attribute)) .ToArray(); if (nodesToRemove.Length != attributeList.Attributes.Count) { //We want to remove only some of the attributes var newAttribute = (AttributeListSyntax)VisitAttributeList( attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia)); newAttributes = newAttributes.Add(newAttribute); } } //Get the leading trivia (the newlines and comments) var leadTriv = node.GetLeadingTrivia(); node = node.WithAttributeLists(newAttributes); //Append the leading trivia to the method node = node.WithLeadingTrivia(leadTriv); return(node); }
public SyntaxList <MemberDeclarationSyntax> AddMember(SyntaxList <MemberDeclarationSyntax> members) { if (!_members.Any()) { return(members); } var newMembersSyntaxList = default(SyntaxList <MemberDeclarationSyntax>); foreach (var buildMember in _members) { newMembersSyntaxList = buildMember.AddMember(newMembersSyntaxList); } newMembersSyntaxList = AddStartRegion(newMembersSyntaxList); newMembersSyntaxList = AddEndRegion(newMembersSyntaxList); foreach (var memberDeclarationSyntax in newMembersSyntaxList) { members = members.Add(memberDeclarationSyntax); } return(members); }
public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax syntaxNode) { IsClassIgnored = syntaxNode.AttributeLists.Any( attributeList => attributeList.Attributes.Any(a => a.Name.ToString().Equals("Ignore"))); var newAttributes = new SyntaxList <AttributeListSyntax>(); foreach (var attributeList in syntaxNode.AttributeLists) { var nodesToRemove = attributeList .Attributes .Where(attribute => attribute.Name.ToString().Equals("Ignore")) .ToArray(); if (nodesToRemove.Length != attributeList.Attributes.Count) { var newAttribute = (AttributeListSyntax)VisitAttributeList( attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia)); newAttributes = newAttributes.Add(newAttribute); } } //Get the leading trivia (the newlines and comments) var leadTriv = syntaxNode.GetLeadingTrivia(); syntaxNode = syntaxNode.WithAttributeLists(newAttributes); //Append the leading trivia to the method syntaxNode = syntaxNode.WithLeadingTrivia(leadTriv); return(base.VisitClassDeclaration(syntaxNode)); }
public SyntaxList <StatementSyntax> ToElementaryOperations( ExpressionSyntax expression, SyntaxToken x) { var kind = expression.Kind(); var result = new SyntaxList <StatementSyntax>(); switch (kind) { case SyntaxKind.NumericLiteralExpression: var list = new SeparatedSyntaxList <ArgumentSyntax>(); list = list.Add(Argument(1.0.ToLiteral())); list = list.Add(Argument(0.0.ToLiteral())); result = result.Add( ReturnStatement( TupleExpression(list))); break; default: throw new NotImplementedException(); } return(result); }
/// <summary> /// Create the public instance properties. /// </summary> /// <param name="members">The structure members.</param> /// <returns>The syntax for creating the public instance properties.</returns> private SyntaxList <MemberDeclarationSyntax> CreatePublicInstanceProperties(SyntaxList <MemberDeclarationSyntax> members) { // This will create the public instance properties. List <SyntaxElement> properties = new List <SyntaxElement>(); properties.Add(new TableProperty(this.tableElement)); properties.Add(new RecordStateProperty()); properties.Add(new IndexProperty(this.tableElement)); // Create a navigation property to each of the parent collections. foreach (ForeignElement foreignKeyElement in this.tableElement.ParentKeys) { properties.Add(new ParentProperty(foreignKeyElement)); } // Create a navigation property to each of the child records. foreach (ForeignElement foreignKeyElement in this.tableElement.ChildKeys) { properties.Add(new ChildrenProperty(foreignKeyElement)); } // Create a property for each column. foreach (ColumnElement columnElement in this.tableElement.Columns) { properties.Add(new ColumnProperty(columnElement)); } // Alphabetize and add the properties as members of the class. foreach (SyntaxElement syntaxElement in properties.OrderBy(m => m.Name)) { members = members.Add(syntaxElement.Syntax); } // Return the new collection of members. return(members); }
public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax syntaxNode) { var newAttributes = new SyntaxList <AttributeListSyntax>(); var isMethodToRefactor = false; IdentifierNameSyntax expectedException = IdentifierName(""); foreach (var attributeList in syntaxNode.AttributeLists) { var nodesToRemove = attributeList .Attributes .Where(attribute => attribute.Name.ToString().Equals("ExpectedException")) .ToArray(); //If the lists are the same length, we are removing all attributes and can just avoid populating newAttributes. if (nodesToRemove.Length > 0) { isMethodToRefactor = true; expectedException = nodesToRemove.First().ArgumentList.DescendantNodes().OfType <IdentifierNameSyntax>().First(); if (nodesToRemove.Length != attributeList.Attributes.Count) { var newAttribute = (AttributeListSyntax)VisitAttributeList( attributeList.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia)); newAttributes = newAttributes.Add(newAttribute); } } else { newAttributes = newAttributes.Add(attributeList); } } //Get the leading trivia (the newlines and comments) var leadTriv = syntaxNode.GetLeadingTrivia(); syntaxNode = syntaxNode.WithAttributeLists(newAttributes); //Append the leading trivia to the method syntaxNode = syntaxNode.WithLeadingTrivia(leadTriv); if (isMethodToRefactor) { var oldBody = syntaxNode.Body; var newBody = Block(ParseStatement("Assert.Throws<" + expectedException.Identifier + ">(()=>" + oldBody + ");")); leadTriv = syntaxNode.GetLeadingTrivia(); syntaxNode = syntaxNode.WithBody(newBody); //Append the leading trivia to the method syntaxNode = syntaxNode.WithLeadingTrivia(leadTriv) .WithModifiers( TokenList( Token( TriviaList( Comment("//HACK: Naive implementation of ExpectedException in XUnit")), SyntaxKind.PublicKeyword, TriviaList()).NormalizeWhitespace())); } //Get the leading trivia (the newlines and comments) return(base.VisitMethodDeclaration(syntaxNode)); }
public override SyntaxNode VisitModuleBlock(ModuleBlockSyntax node) { var initInvocations = new SyntaxList <StatementSyntax>(); var space = SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " "); var newline = SyntaxFactory.SyntaxTrivia(SyntaxKind.EndOfLineTrivia, Environment.NewLine); for (int a = 0; a < node.Members.Count; a++) { if (node.Members[a].IsKind(SyntaxKind.FieldDeclaration)) { foreach (var declarators in (node.Members[a] as FieldDeclarationSyntax).Declarators) { // Checks for variable declaration string item = declarators?.AsClause?.Type().WithoutTrivia().ToString(); if (structuresWithInit.Contains(item)) { foreach (var name in declarators.Names) { if (name.ArrayBounds != null) { initInvocations.Add( CreateInitializer( name.Identifier.ToFullString().Trim(), item, true) .WithTrailingTrivia(newline)); } else { initInvocations.Add( CreateInitializer( name.Identifier.ToFullString().Trim(), item, false) .WithTrailingTrivia(newline)); } } } // end check of structures } } // end check of field declarations } if (initInvocations.Count > 0) { // Sub New() Statement var subStart = SyntaxFactory.SubStatement( SyntaxFactory.Identifier("New()").WithLeadingTrivia(space)) .WithLeadingTrivia(newline) .WithTrailingTrivia(newline); // End Sub statement var subEnd = SyntaxFactory.EndSubStatement( SyntaxFactory.Token(SyntaxKind.EndIfKeyword, "End ").WithLeadingTrivia(newline), SyntaxFactory.Token(SyntaxKind.SubKeyword, "Sub")) .WithTrailingTrivia(newline); // Initializer for the module part of the transpiled file var moduleConstructor = SyntaxFactory.SubBlock(subStart, initInvocations, subEnd); // WithMembers => adds the specified members to the node declaration // it makes sense because the node is the root (I think) node = node.WithMembers(node.Members.Add(moduleConstructor)); } // Since we want to continue the visit, we call the base method return(base.VisitModuleBlock(node)); }
private static void ReplaceMethodTextCSharp(SyntaxNode node, IDocument document, string textToSearch) { string methodText = node.GetText().ToString(); bool isMethod = node is MethodDeclarationSyntax; string methodOrPropertyDefinition = isMethod ? "Method: " : " Invalid - not Method "; object methodName = ((MethodDeclarationSyntax)node).Identifier.Value; var body = (node as MethodDeclarationSyntax).Body; var statements = body.Statements; var originalTrailingTrivia = body.GetTrailingTrivia(); SyntaxList<StatementSyntax> newStatements = new SyntaxList<StatementSyntax>(); StatementSyntax statementNewTestmap = Syntax.ParseStatement("var testmap = new Dictionary<string, object>();"); newStatements = newStatements.Add(statementNewTestmap); SyntaxList<StatementSyntax> flattenedStmts = Flatten(statements); foreach (var statement in flattenedStmts) { //string stmtString = RemoveComments(statement).ToString(); string stmtString = statement.ToString(); stmtString = RemoveComments(stmtString); if (Regex.IsMatch(stmtString, "\\b" + textToSearch + "\\b")) { StatementSyntax newStatement = null; //string[] parameters = stmtString.Split(new char[] { '(', ',', ')' }); //if(parameters.Length == 4) //{ // if(parameters.Last() == "1") // { // Console.WriteLine(stmtString); // } //} //stmtString = TestmapAdd + "(" + parameters.ElementAt(1) + ", " + parameters.ElementAt(2) + ");" ; var invocation = Syntax.ParseExpression(RemoveComments(stmtString)) as InvocationExpressionSyntax; var args = invocation.ArgumentList.Arguments; //var args = GetParams(stmtString); if (args.Count() > 3) { throw new Exception(); } if (args.Count() == 3) { #if DEBUG if (args.Last().ToString() != "0") Console.WriteLine(stmtString); #endif // Console.WriteLine(stmtString); //stmtString = TestmapAdd + "(" + args.ElementAt(0) + ", " + args.ElementAt(1) + ");"; try { var registerArgs = new List<ArgumentSyntax> { args.ElementAt(0), args.ElementAt(1) }; var argSeparators = Enumerable.Repeat(Syntax.Token(SyntaxKind.CommaToken), registerArgs.Count - 1).ToList(); ArgumentListSyntax newArgList = Syntax.ArgumentList( arguments: Syntax.SeparatedList( registerArgs, argSeparators)); InvocationExpressionSyntax newInvokationNode = Syntax.InvocationExpression( Syntax.MemberAccessExpression( kind: SyntaxKind.MemberAccessExpression, expression: Syntax.ParseName("testmap"), name: Syntax.IdentifierName("Add"), operatorToken: Syntax.Token(SyntaxKind.DotToken)), newArgList); stmtString = newInvokationNode.ToString() + ";"; newStatement = Syntax.ParseStatement(stmtString); } catch(Exception e) { Console.WriteLine(e); } } if(args.Count() == 2) { stmtString = stmtString.Replace(textToSearch, TestmapAdd); } Console.WriteLine(stmtString); newStatement = Syntax.ParseStatement(stmtString); try { newStatements = newStatements.Add(newStatement); } catch (Exception e) { Console.WriteLine(e); } //stmtString.Replace(textToSearch, "thisTest.GenericVerify"); } else newStatements = newStatements.Add(statement); } newStatements = newStatements.Add(Syntax.ParseStatement("thisTest.GenericVerify(testmap);")); FileRoot = FileRoot.ReplaceNode(body, Syntax.Block(newStatements).WithTrailingTrivia(originalTrailingTrivia)).NormalizeWhitespace(); }
Document PerformAction(Document document, SemanticModel model, SyntaxNode root, PropertyBlockSyntax propertyDeclaration, bool needsSetter) { AccessorBlockSyntax accessor = null; PropertyBlockSyntax newProp = null; if (needsSetter) { accessor = SyntaxFactory.AccessorBlock( SyntaxKind.SetAccessorBlock, SyntaxFactory.AccessorStatement(SyntaxKind.SetAccessorStatement, SyntaxFactory.Token(SyntaxKind.SetKeyword)) .WithParameterList(SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(new[] { SyntaxFactory.Parameter(SyntaxFactory.List<AttributeListSyntax>(), SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ByValKeyword)), SyntaxFactory.ModifiedIdentifier("value"), SyntaxFactory.SimpleAsClause(propertyDeclaration.PropertyStatement.AsClause.Type().WithoutTrailingTrivia()), null) }))), SyntaxFactory.EndBlockStatement(SyntaxKind.EndSetStatement, SyntaxFactory.Token(SyntaxKind.SetKeyword))); var getter = propertyDeclaration.Accessors.FirstOrDefault(m => m.IsKind(SyntaxKind.GetAccessorBlock)); if (getter != null) { var getField = getter.ScanGetter(model); if (getField == null || getField.IsReadOnly) { // Readonly or no field can be found accessor = accessor.WithStatements(SyntaxFactory.List<StatementSyntax>(new[] { GetNotImplementedThrowStatement() })); } else { // Now we add a 'field = value'. accessor = accessor.WithStatements(SyntaxFactory.List<StatementSyntax>(new[] { SyntaxFactory.AssignmentStatement(SyntaxKind.SimpleAssignmentStatement, SyntaxFactory.IdentifierName(getField.Name), SyntaxFactory.Token(SyntaxKind.EqualsToken), SyntaxFactory.IdentifierName("value")) })); } } var modifierList = SyntaxFactory.TokenList(propertyDeclaration.PropertyStatement.Modifiers.Where(m => !m.IsKind(SyntaxKind.ReadOnlyKeyword))); newProp = propertyDeclaration .WithAccessors(propertyDeclaration.Accessors.Add(accessor)) .WithPropertyStatement(propertyDeclaration.PropertyStatement.WithModifiers(modifierList)); } else { accessor = SyntaxFactory.AccessorBlock(SyntaxKind.GetAccessorBlock, SyntaxFactory.AccessorStatement(SyntaxKind.GetAccessorStatement, SyntaxFactory.Token(SyntaxKind.GetKeyword)), SyntaxFactory.EndBlockStatement(SyntaxKind.EndGetStatement, SyntaxFactory.Token(SyntaxKind.GetKeyword))); var setter = propertyDeclaration.Accessors.FirstOrDefault(m => m.IsKind(SyntaxKind.SetAccessorBlock)); var accessorDeclList = new SyntaxList<AccessorBlockSyntax>(); if (setter != null) { var setField = setter.ScanSetter(model); if (setField == null) { // No field can be found accessor = accessor.WithStatements(SyntaxFactory.List<StatementSyntax>(new[] { GetNotImplementedThrowStatement() })); } else { // Add a 'Return field'. accessor = accessor.WithStatements(SyntaxFactory.List<StatementSyntax>( new[] { SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(setField.Name)) })); } accessorDeclList = accessorDeclList.Add(propertyDeclaration.Accessors.First(m => m.IsKind(SyntaxKind.SetAccessorBlock))); } accessorDeclList = accessorDeclList.Insert(0, accessor); var accessorList = SyntaxFactory.List(accessorDeclList); var modifierList = SyntaxFactory.TokenList(propertyDeclaration.PropertyStatement.Modifiers.Where(m => !m.IsKind(SyntaxKind.WriteOnlyKeyword))); newProp = propertyDeclaration .WithAccessors(accessorList) .WithPropertyStatement(propertyDeclaration.PropertyStatement.WithModifiers(modifierList)); } var newRoot = root.ReplaceNode(propertyDeclaration, newProp).WithAdditionalAnnotations(Formatter.Annotation); return document.WithSyntaxRoot(newRoot); }
private async Task <Document> CreateChangedDocumentAsync(CodeFixContext context, DocumentationCommentTriviaSyntax documentationCommentTriviaSyntax, CancellationToken cancellationToken) { StringBuilder leadingTriviaBuilder = new StringBuilder(); SyntaxToken parentToken = documentationCommentTriviaSyntax.ParentTrivia.Token; int documentationCommentIndex = parentToken.LeadingTrivia.IndexOf(documentationCommentTriviaSyntax.ParentTrivia); for (int i = 0; i < documentationCommentIndex; i++) { SyntaxTrivia trivia = parentToken.LeadingTrivia[i]; switch (trivia.Kind()) { case SyntaxKind.EndOfLineTrivia: leadingTriviaBuilder.Clear(); break; case SyntaxKind.WhitespaceTrivia: leadingTriviaBuilder.Append(trivia.ToFullString()); break; default: break; } } leadingTriviaBuilder.Append(documentationCommentTriviaSyntax.GetLeadingTrivia().ToFullString()); // this is the trivia that should appear at the beginning of each line of the comment. SyntaxTrivia leadingTrivia = SyntaxFactory.DocumentationCommentExterior(leadingTriviaBuilder.ToString()); string newLineText = context.Document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); var documentedSymbol = semanticModel.GetDeclaredSymbol(parentToken.Parent.FirstAncestorOrSelf <SyntaxNode>(SyntaxNodeExtensionsEx.IsSymbolDeclaration), context.CancellationToken); DocumentationCommentTriviaSyntax contentsOnly = RemoveExteriorTrivia(documentationCommentTriviaSyntax); contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.ChildNodes(), (originalNode, rewrittenNode) => RenderBlockElementAsMarkdown(originalNode, rewrittenNode, newLineText, documentedSymbol)); string renderedContent = contentsOnly.Content.ToFullString(); string[] lines = renderedContent.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None); SyntaxList <XmlNodeSyntax> newContent = XmlSyntaxFactory.List(); for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (string.IsNullOrWhiteSpace(line)) { if (i == lines.Length - 1) { break; } line = string.Empty; } if (newContent.Count > 0) { newContent = newContent.Add(XmlSyntaxFactory.NewLine(newLineText).WithTrailingTrivia(SyntaxFactory.DocumentationCommentExterior("///"))); } newContent = newContent.Add(XmlSyntaxFactory.Text(line.TrimEnd(), xmlEscape: false)); } contentsOnly = contentsOnly.WithContent(newContent); contentsOnly = contentsOnly .ReplaceExteriorTrivia(leadingTrivia) .WithLeadingTrivia(SyntaxFactory.DocumentationCommentExterior("///")) .WithTrailingTrivia(SyntaxFactory.EndOfLine(Environment.NewLine)); string fullContent = contentsOnly.ToFullString(); SyntaxTriviaList parsedTrivia = SyntaxFactory.ParseLeadingTrivia(fullContent); SyntaxTrivia documentationTrivia = parsedTrivia.FirstOrDefault(i => i.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia)); contentsOnly = documentationTrivia.GetStructure() as DocumentationCommentTriviaSyntax; if (contentsOnly == null) { return(context.Document); } // Remove unnecessary nested paragraph elements contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), MarkUnnecessaryParagraphs); contentsOnly = contentsOnly.ReplaceNodes(contentsOnly.DescendantNodes().OfType <XmlElementSyntax>(), RemoveUnnecessaryParagraphs); SyntaxNode root = await context.Document.GetSyntaxRootAsync(cancellationToken); SyntaxNode newRoot = root.ReplaceNode(documentationCommentTriviaSyntax, contentsOnly); if (documentationCommentTriviaSyntax.IsEquivalentTo(contentsOnly)) { return(context.Document); } if (documentationCommentTriviaSyntax.ToFullString().Equals(contentsOnly.ToFullString(), StringComparison.Ordinal)) { return(context.Document); } return(context.Document.WithSyntaxRoot(newRoot)); }
private static SyntaxList<StatementSyntax> Flatten(StatementSyntax stmt, SyntaxList<StatementSyntax> result) { if (!(stmt is BlockSyntax)) result = result.Add(stmt); else { foreach(var item in (stmt as BlockSyntax).Statements) { result = Flatten(item, result); } } return result; }
private static SyntaxList<StatementSyntax> Flatten(SyntaxList<StatementSyntax> statements) { SyntaxList<StatementSyntax> result = new SyntaxList<StatementSyntax>(); foreach(var stmt in statements) { if (!(stmt is BlockSyntax)) result = result.Add(stmt); else result = Flatten(stmt, result); } return result; }
public CodeActionEdit GetEdit(CancellationToken cancellationToken) { SyntaxNode root = (SyntaxNode)this.document.GetSyntaxRoot(cancellationToken); ISemanticModel model = this.document.GetSemanticModel(cancellationToken); // Mechanics: // (1) Create new type declaration // (2) Remove parameters from method declaration and insert ParameterObject instance in place // (3) Remove arguments from method invocations and insert ParameterObject creation in place // (4) Replace references to parameters with references to properties from ParameterObjectInstance within method body const string className = "ParameterObject"; const string parameterObjectName = "parameterObject"; // Fetch BaseMethodDeclaration node and its symbol BaseMethodDeclarationSyntax methodDeclaration = this.parameters.First().FirstAncestorOrSelf <BaseMethodDeclarationSyntax>(); ISymbol methodSymbol = model.GetDeclaredSymbol(methodDeclaration); // Create declaration of new aggregate class SeparatedSyntaxList <ParameterSyntax> ctorParameters = Syntax.SeparatedList <ParameterSyntax>(); SyntaxList <StatementSyntax> ctorStatements = Syntax.List <StatementSyntax>(); SyntaxList <MemberDeclarationSyntax> classMembers = Syntax.List <MemberDeclarationSyntax>(); foreach (ParameterSyntax parameter in this.parameters) { // Get parameter identifier SyntaxToken identifier = parameter.Identifier; // Get parameter type TypeSyntax parameterType = parameter.Type; // Create new parameter ParameterSyntax ctorParameter = Syntax.Parameter(identifier) .WithType(parameterType); ctorParameters = ctorParameters.Add(ctorParameter); // Create new property to store argument value PropertyDeclarationSyntax propertyDeclaration = Syntax.PropertyDeclaration(parameterType, identifier) .WithModifiers(Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword))) .WithTrailingTrivia(Syntax.CarriageReturnLineFeed) .WithAccessorList( Syntax.AccessorList(Syntax.List <AccessorDeclarationSyntax>( Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)), Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration) .WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)) )).WithTrailingTrivia(Syntax.CarriageReturnLineFeed) ); classMembers = classMembers.Add(propertyDeclaration); // Create ctor initializing statement: // Considers: // this.a = a; ExpressionStatementSyntax statement = Syntax.ExpressionStatement( Syntax.BinaryExpression(SyntaxKind.AssignExpression, Syntax.MemberAccessExpression(SyntaxKind.MemberAccessExpression, Syntax.ThisExpression(), Syntax.IdentifierName(identifier)), Syntax.IdentifierName(identifier) )); ctorStatements = ctorStatements.Add(statement); } ConstructorDeclarationSyntax ctorDeclaration = Syntax.ConstructorDeclaration(className) .WithModifiers(Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword))) .WithBody(Syntax.Block(ctorStatements)) .WithParameterList(Syntax.ParameterList(ctorParameters)); classMembers = classMembers.Add(ctorDeclaration); ClassDeclarationSyntax classDeclaration = Syntax.ClassDeclaration(className) .WithMembers(classMembers) .WithLeadingTrivia(Syntax.ElasticCarriageReturnLineFeed) .WithTrailingTrivia(Syntax.CarriageReturnLineFeed) .WithAdditionalAnnotations(CodeAnnotations.Formatting); IntroduceParameterObjectRewriter visitor = new IntroduceParameterObjectRewriter(model, cancellationToken, this.parameters, methodSymbol, parameterObjectName); SyntaxNode newRoot = visitor.Visit(root); // Add new class declaration to compilation unit CompilationUnitSyntax compilationUnit = newRoot.FirstAncestorOrSelf <CompilationUnitSyntax>(); CompilationUnitSyntax newCompilationUnit = compilationUnit.AddMembers(classDeclaration); newRoot = newRoot.ReplaceNode(compilationUnit, newCompilationUnit); return(new CodeActionEdit(this.document.UpdateSyntaxRoot(newRoot))); }
public static SyntaxList <XmlNodeSyntax> WithoutFirstAndLastNewlines(this SyntaxList <XmlNodeSyntax> summaryContent) { if (summaryContent.Count == 0) { return(summaryContent); } XmlTextSyntax firstSyntax = summaryContent[0] as XmlTextSyntax; if (firstSyntax == null) { return(summaryContent); } XmlTextSyntax lastSyntax = summaryContent[summaryContent.Count - 1] as XmlTextSyntax; if (lastSyntax == null) { return(summaryContent); } SyntaxTokenList firstSyntaxTokens = firstSyntax.TextTokens; int removeFromStart; if (IsXmlNewLine(firstSyntaxTokens[0])) { removeFromStart = 1; } else { if (!IsXmlWhitespace(firstSyntaxTokens[0])) { return(summaryContent); } if (!IsXmlNewLine(firstSyntaxTokens[1])) { return(summaryContent); } removeFromStart = 2; } SyntaxTokenList lastSyntaxTokens = lastSyntax.TextTokens; int removeFromEnd; if (IsXmlNewLine(lastSyntaxTokens[lastSyntaxTokens.Count - 1])) { removeFromEnd = 1; } else { if (!IsXmlWhitespace(lastSyntaxTokens[lastSyntaxTokens.Count - 1])) { return(summaryContent); } if (!IsXmlNewLine(lastSyntaxTokens[lastSyntaxTokens.Count - 2])) { return(summaryContent); } removeFromEnd = 2; } for (int i = 0; i < removeFromStart; i++) { firstSyntaxTokens = firstSyntaxTokens.RemoveAt(0); } if (firstSyntax == lastSyntax) { lastSyntaxTokens = firstSyntaxTokens; } for (int i = 0; i < removeFromEnd; i++) { if (!lastSyntaxTokens.Any()) { break; } lastSyntaxTokens = lastSyntaxTokens.RemoveAt(lastSyntaxTokens.Count - 1); } summaryContent = summaryContent.RemoveAt(summaryContent.Count - 1); if (lastSyntaxTokens.Count != 0) { summaryContent = summaryContent.Add(lastSyntax.WithTextTokens(lastSyntaxTokens)); } if (firstSyntax != lastSyntax) { summaryContent = summaryContent.RemoveAt(0); if (firstSyntaxTokens.Count != 0) { summaryContent = summaryContent.Insert(0, firstSyntax.WithTextTokens(firstSyntaxTokens)); } } if (summaryContent.Count > 0) { // Make sure to remove the leading trivia summaryContent = summaryContent.Replace(summaryContent[0], summaryContent[0].WithLeadingTrivia()); // Remove leading spaces (between the <para> start tag and the start of the paragraph content) XmlTextSyntax firstTextSyntax = summaryContent[0] as XmlTextSyntax; if (firstTextSyntax != null && firstTextSyntax.TextTokens.Count > 0) { SyntaxToken firstTextToken = firstTextSyntax.TextTokens[0]; string firstTokenText = firstTextToken.Text; string trimmed = firstTokenText.TrimStart(); if (trimmed != firstTokenText) { SyntaxToken newFirstToken = SyntaxFactory.Token( firstTextToken.LeadingTrivia, firstTextToken.Kind(), trimmed, firstTextToken.ValueText.TrimStart(), firstTextToken.TrailingTrivia); summaryContent = summaryContent.Replace(firstTextSyntax, firstTextSyntax.ReplaceToken(firstTextToken, newFirstToken)); } } } return(summaryContent); }
private async static Task <Document> SwitchWithoutDefaultAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var switchCaseLabel = new SyntaxList <SwitchLabelSyntax>(); var kindOfVariable = string.Empty; var idForVariable = string.Empty; var breakStatement = new SyntaxList <StatementSyntax>(); var diagnosticSpan = diagnostic.Location.SourceSpan; var newSections = new List <SwitchSectionSyntax>(); var switchCaseStatement = root.FindToken(diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType <SwitchStatementSyntax>().First(); idForVariable = ((IdentifierNameSyntax)switchCaseStatement.ChildNodes().ToList().First(n => n.Kind() == SyntaxKind.IdentifierName)).Identifier.ValueText; var parametersOfMethod = from init in root.DescendantNodesAndSelf() where init.Kind() == SyntaxKind.Parameter select init; // Verify if the variable of Switch as a same of Method Parameter foreach (var parameter in parametersOfMethod) { if (idForVariable == ((ParameterSyntax)parameter).Identifier.ValueText) { kindOfVariable = ((ParameterSyntax)parameter).Type.ToString(); } } if (kindOfVariable == string.Empty) { var statements = ((BlockSyntax)switchCaseStatement.Parent).Statements; var inicializerOfSwitch = from init in statements where init.Kind() == SyntaxKind.LocalDeclarationStatement select init; if (inicializerOfSwitch.Any()) { var local = (LocalDeclarationStatementSyntax)inicializerOfSwitch.First(); var switchCaseVariable = ((local).Declaration).Variables[0]; kindOfVariable = ((LiteralExpressionSyntax)(switchCaseVariable.Initializer.Value)).Kind().ToString(); } } if ((kindOfVariable.Equals("FalseLiteralExpression")) || (kindOfVariable.Equals("TrueLiteralExpression")) || (kindOfVariable.Equals("bool"))) { var oldSections = switchCaseStatement.Sections.ToList(); var type = string.Empty; foreach (var sec in oldSections) { newSections.Add(sec); type = (((CaseSwitchLabelSyntax)((SwitchSectionSyntax)sec).ChildNodes().ToList().First()).Value).GetFirstToken().Text; } var againstType = string.Empty; if (type.Equals("true")) { againstType = "false"; } else { againstType = "true"; } newSections.Add(SyntaxFactory.SwitchSection().WithLabels( switchCaseLabel.Add(SyntaxFactory.CaseSwitchLabel(SyntaxFactory.ParseExpression(againstType)))). WithStatements(breakStatement.Add(SyntaxFactory.ParseStatement(BreakString)))); } else { var oldSections = switchCaseStatement.Sections.ToList(); foreach (var sec in oldSections) { newSections.Add(sec); } breakStatement = breakStatement.Add(SyntaxFactory.ParseStatement(BreakString)); newSections.Add(CreateSection(SyntaxFactory.DefaultSwitchLabel(), SyntaxFactory.ParseStatement(ThrowString))); } var switchExpression = SyntaxFactory.ParseExpression(idForVariable); var newsSwitchCaseStatement = SyntaxFactory.SwitchStatement(switchExpression). WithSections(new SyntaxList <SwitchSectionSyntax>().AddRange(newSections)); var newRoot = root.ReplaceNode(switchCaseStatement, newsSwitchCaseStatement); var newDocument = document.WithSyntaxRoot(newRoot); return(newDocument); }
private static List <StatementSyntax> HandleSyntaxInMap(FieldNamesValidator fieldValidator, MapFunctionProcessor mapRewriter, ExpressionSyntax expression, ref SyntaxList <MemberDeclarationSyntax> members) { var rewrittenExpression = (CSharpSyntaxNode)mapRewriter.Visit(expression); StatementSyntax optimized = null; try { var visitor = new RavenLinqOptimizer(fieldValidator); optimized = visitor.Visit(new RavenLinqPrettifier().Visit(rewrittenExpression)) as StatementSyntax; } catch (NotSupportedException) { // there are certain patterns we aren't optimizing, that is fine } var collectionName = string.IsNullOrWhiteSpace(mapRewriter.CollectionName) ? Constants.Documents.Collections.AllDocumentsCollection : mapRewriter.CollectionName; var collection = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(collectionName)); var results = new List <StatementSyntax>(); if (optimized != null) { var method = SyntaxFactory.MethodDeclaration(SyntaxFactory.IdentifierName("IEnumerable"), SyntaxFactory.Identifier("Map_" + members.Count)) .WithParameterList( SyntaxFactory.ParameterList(SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Parameter(SyntaxFactory.Identifier("docs")) .WithType( SyntaxFactory.GenericName("IEnumerable") .WithTypeArgumentList( SyntaxFactory.TypeArgumentList( SyntaxFactory.SingletonSeparatedList <TypeSyntax>(SyntaxFactory.IdentifierName("dynamic")) ) ) ) )) ) .WithBody(SyntaxFactory.Block().AddStatements(optimized)); members = members.Add(method); results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddMap)).Invoke(collection, RoslynHelper.This(method.Identifier.Text)).AsExpressionStatement()); // this.AddMap("Users", docs => from doc in docs ... ) } else { var indexingFunction = SyntaxFactory.SimpleLambdaExpression(SyntaxFactory.Parameter(SyntaxFactory.Identifier("docs")), rewrittenExpression); results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddMap)).Invoke(collection, indexingFunction).AsExpressionStatement()); // this.AddMap("Users", docs => from doc in docs ... ) } if (mapRewriter.ReferencedCollections != null) { foreach (var referencedCollection in mapRewriter.ReferencedCollections) { var rc = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(referencedCollection)); results.Add(RoslynHelper.This(nameof(StaticIndexBase.AddReferencedCollection)).Invoke(collection, rc).AsExpressionStatement()); } } return(results); }
private SyntaxList <AttributeListSyntax> DoRefactor(Dictionary <HttpStatusCode, AttributeMetadata> updatedList, MethodDeclarationSyntax method) { /* These are the codes that will be added after updating the existing ones. * They MUST be set to false from this Dictionary as the existing attributes * are updated. */ Dictionary <HttpStatusCode, bool> statusCodesToAdd = updatedList.ToDictionary(k => k.Key, v => true); /* First, update existing */ SyntaxList <AttributeListSyntax> clonedAttributes = method.AttributeLists; for (int index = 0; index < clonedAttributes.Count; index++) { AttributeListSyntax att = clonedAttributes[index]; if (att.GetName() != AttributeName) { continue; } List <AttributeArgumentSyntax> arguments = GetAttributeArguments(att).ToList(); HttpStatusCode code; if (!GetStatusCode(arguments[0], out code)) { throw new NotImplementedException(); } AttributeMetadata newAttribute = updatedList[code]; /* Create type definition */ AttributeArgumentSyntax typeArgument = null; if (newAttribute.TypeName != null) { typeArgument = SyntaxFactory.AttributeArgument(null, null, SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseName(newAttribute.TypeName))); } SeparatedSyntaxList <AttributeArgumentSyntax> args = new SeparatedSyntaxList <AttributeArgumentSyntax>(); args = args.Add(arguments[0]); args = args.Add(arguments[1]); if (typeArgument != null) { args = args.Add(typeArgument); } /* Compile arguments ito a new attribute */ SeparatedSyntaxList <AttributeSyntax> attributeWhole = CreateAttribute(args); clonedAttributes = clonedAttributes.Replace(att, SyntaxFactory.AttributeList(att.OpenBracketToken, att.Target, attributeWhole, att.CloseBracketToken)); /* Update statusCodesToAdd */ statusCodesToAdd[code] = false; } /* Return here if there are no attributes to add */ if (!statusCodesToAdd.Any(v => v.Value)) { return(clonedAttributes); } /* Add new attributes */ IEnumerable <AttributeMetadata> attributes = updatedList.Where(kv => statusCodesToAdd[kv.Key]).Select(a => a.Value); foreach (AttributeMetadata attributeToAdd in attributes) { SeparatedSyntaxList <AttributeArgumentSyntax> args = new SeparatedSyntaxList <AttributeArgumentSyntax>(); /* Add status code */ args = args.Add(SyntaxFactory.AttributeArgument(null, null, SyntaxFactory.ParseName($"{StatusCodeEnumName}.{attributeToAdd.StatusCode}"))); /* Add default description */ args = args.Add(SyntaxFactory.AttributeArgument(null, null, SyntaxFactory.ParseName($"\"{attributeToAdd.Description}\""))); /* And, if applicable, add type */ if (attributeToAdd.TypeName != null) { args = args.Add(SyntaxFactory.AttributeArgument(null, null, SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseName(attributeToAdd.TypeName)))); } AttributeListSyntax attribute = SyntaxFactory.AttributeList(SyntaxFactory.Token(SyntaxKind.OpenBracketToken), null, CreateAttribute(args), SyntaxFactory.Token(SyntaxKind.CloseBracketToken)); clonedAttributes = clonedAttributes.Add(attribute); } return(clonedAttributes); }
private SyntaxList <StatementSyntax> EmitTypesMemberSerialization(ITypeSymbol currentType, SyntaxList <StatementSyntax> statements) { if (currentType is INamedTypeSymbol namedSymbol) { if (namedSymbol.IsUnboundGenericType) { throw new InvalidOperationException($"Cannot emit member serialization for open generic Type: {namedSymbol.Name}"); } } //Conceptually, we need to find ALL serializable members foreach (ISymbol mi in currentType .GetMembers() .Where(m => !m.IsStatic) .Where(m => m.HasAttributeExact <WireMemberAttribute>()) .OrderBy(m => { //Seperated lines for debugging purposes. AttributeData attri = m.GetAttributeExact <WireMemberAttribute>(); ImmutableArray <TypedConstant> attriArgs = attri.ConstructorArguments; string value = attriArgs.First().ToCSharpString(); return(WireMemberAttribute.Parse(value)); })) //order is important, we must emit in order!! { //Basically doesn't matter if it's a field or property, we just wanna know the Type //The reason is, setting and getting fields vs members are same syntax ITypeSymbol memberType = GetMemberTypeInfo(mi); AnalyzeMemberTypeForGenerics(memberType); FieldDocumentationStatementsBlockEmitter commentEmitter = new FieldDocumentationStatementsBlockEmitter(memberType, mi); statements = statements.AddRange(commentEmitter.CreateStatements()); //The serializer is requesting we DON'T WRITE THIS! So we skip if (Mode == SerializationMode.Write) { if (mi.HasAttributeExact <DontWriteAttribute>()) { continue; } } else if (Mode == SerializationMode.Read) { if (mi.HasAttributeExact <DontReadAttribute>()) { continue; } } //This handles OPTIONAL fields that may or may not be included if (mi.HasAttributeExact <OptionalAttribute>()) { OptionalFieldStatementsBlockEmitter emitter = new OptionalFieldStatementsBlockEmitter(memberType, mi); statements = statements.AddRange(emitter.CreateStatements()); } InvocationExpressionSyntax invokeSyntax = null; //We know the type, but we have to do special handling depending on on its type if (mi.HasAttributeExact <CustomTypeSerializerAttribute>() || memberType.HasAttributeExact <CustomTypeSerializerAttribute>()) { //So TYPES and PROPERTIES may both reference a custom serializer. //So we should prefer field/prop attributes over the type. AttributeData attribute = mi.HasAttributeExact <CustomTypeSerializerAttribute>() ? mi.GetAttributeExact <CustomTypeSerializerAttribute>() : memberType.GetAttributeExact <CustomTypeSerializerAttribute>(); //It's DEFINITELY not null. OverridenSerializationGenerator emitter = new OverridenSerializationGenerator(memberType, mi, Mode, (ITypeSymbol)attribute.ConstructorArguments.First().Value); invokeSyntax = emitter.Create(); } else if (memberType.IsPrimitive()) { //Easy case of primitive serialization PrimitiveTypeSerializationStatementsBlockEmitter emitter = new PrimitiveTypeSerializationStatementsBlockEmitter(memberType, mi, Mode); invokeSyntax = emitter.Create(); } else if (memberType.SpecialType == SpecialType.System_String) { var emitter = new StringTypeSerializationStatementsBlockEmitter(memberType, mi, Mode); invokeSyntax = emitter.Create(); } else if (memberType.SpecialType == SpecialType.System_Array || memberType is IArrayTypeSymbol) { var emitter = new ArrayTypeSerializationStatementsBlockEmitter((IArrayTypeSymbol)memberType, mi, Mode); invokeSyntax = emitter.Create(); } else if (memberType.IsEnumType()) //Enum type { var emitter = new EnumTypeSerializerStatementsBlockEmitter(memberType, mi, Mode); invokeSyntax = emitter.Create(); } else if (memberType.IsReferenceType && memberType.TypeKind == TypeKind.Class) { var emitter = new ComplexTypeSerializerStatementsBlockEmitter((INamedTypeSymbol)memberType, mi, Mode); invokeSyntax = emitter.Create(); } else { bool isGenericType = currentType is INamedTypeSymbol n && n.IsGenericType; bool isUnboundedGenericType = currentType is INamedTypeSymbol n2 && n2.IsUnboundGenericType; throw new NotImplementedException($"TODO: Cannot handle Type: {memberType} ContainingType: {currentType} MetadataType: {currentType.GetType().Name} Generic: {isGenericType} UnboundGeneric: {isUnboundedGenericType}"); } //Now we check if compression was requested if (invokeSyntax != null && mi.HasAttributeExact <CompressAttribute>()) { TypeNameTypeCollector collector = new TypeNameTypeCollector(); collector.Visit(invokeSyntax); //Replace the invokcation with an invokation to the compression decorator. FullSerializerMethodInvokationEmitter emitter = new FullSerializerMethodInvokationEmitter(Mode, $"{WoWZLibCompressionTypeSerializerDecorator.TYPE_NAME}<{collector.Types.First().ToFullString()}, {memberType.ToFullName()}>", mi); invokeSyntax = emitter.Create(); } if (invokeSyntax != null) { if (Mode == SerializationMode.Write) { statements = statements.Add(invokeSyntax.ToStatement()); } else if (Mode == SerializationMode.Read) { //Read generation is abit more complicated. //We must emit the assignment too ReadAssignmentStatementsBlockEmitter emitter = new ReadAssignmentStatementsBlockEmitter(memberType, mi, Mode, invokeSyntax); statements = statements.AddRange(emitter.CreateStatements()); } } //TODO: These don't work!! //Add 2 line breaks //statements = statements.AddRange(new EmptyLineStatementBlockEmitter().CreateStatements()); //statements = statements.AddRange(new EmptyLineStatementBlockEmitter().CreateStatements()); } return(statements); }
public static CompiledFile Read(string fileName, string Code, List <string> foundAssemblies, out string RawCode) { string Name = $"CsTask{Guid.NewGuid().ToString().Replace("-", "")}"; RawCode = Code; CompiledFile file = new CompiledFile(); file.Name = fileName; SyntaxTree syntax = null; bool retry = false; bool wrapStatic = false; file.ReferencedAssemblies = foundAssemblies ?? new List <string>(); RETRY: file.ReferencedAssemblies = file.ReferencedAssemblies.Distinct().ToList(); if (retry) //Failed and a CS0116 error, retry with wrapping in static classs { var root = syntax.GetRoot() as CompilationUnitSyntax; var usings = root.Usings.ToFullString(); SyntaxList <MemberDeclarationSyntax> newMembers = new SyntaxList <MemberDeclarationSyntax>(); var members = root.Members; foreach (var mem in members) { var staticToken = SyntaxFactory.Token(SyntaxKind.StaticKeyword); var realStaticToken = staticToken.WithTrailingTrivia(SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia, " ")); if (mem is MethodDeclarationSyntax method) { if (!method.Modifiers.Any(x => x.Text == staticToken.Text)) { newMembers = newMembers.Add(method.AddModifiers(realStaticToken)); } else { newMembers = newMembers.Add(method); } } else if (mem is PropertyDeclarationSyntax prop) { if (!prop.Modifiers.Any(x => x.Text == staticToken.Text)) { newMembers = newMembers.Add(prop.AddModifiers(realStaticToken)); } else { newMembers = newMembers.Add(prop); } } else if (mem is FieldDeclarationSyntax field) { if (!field.Modifiers.Any(x => x.Text == staticToken.Text)) { newMembers = newMembers.Add(field.AddModifiers(realStaticToken)); } else { newMembers = newMembers.Add(field); } } else { newMembers = newMembers.Add(mem); } } root = root.WithMembers(newMembers); var txt = root.GetText(); var fullTxt = txt.ToString(); RawCode = fullTxt; if (!string.IsNullOrWhiteSpace(usings)) { fullTxt = fullTxt.Replace(usings, ""); } if (wrapStatic) { Code = $@" {usings} static class {Name}{{ {fullTxt} }} "; } else { Code = $@" {usings} {fullTxt} "; } wrapStatic = false; retry = false; } syntax = CSharpSyntaxTree.ParseText(Code); List <MetadataReference> references = new List <MetadataReference> { MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(Regex).GetTypeInfo().Assembly.Location) }; foreach (var ass in file.ReferencedAssemblies) { Assembly loaded = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(ass)); references.Add(MetadataReference.CreateFromFile(loaded.Location)); } CSharpCompilation compilation = CSharpCompilation.Create( Name, syntaxTrees: new[] { syntax }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using (var ms = new MemoryStream()) { EmitResult result = compilation.Emit(ms); if (!result.Success) { if (result.Diagnostics.Any(x => x.ToString().Contains("CS0116"))) //Failed and a CS0116 error, retry with wrapping in static classs { wrapStatic = true; retry = true; } IEnumerable <Diagnostic> failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); if (failures.Any(x => x.Id == "CS0012")) { var infoMember = failures.FirstOrDefault().GetType().GetMembers().SingleOrDefault(x => x.Name == "get_Info") as MethodInfo; var argumentField = infoMember.ReturnType.GetTypeInfo().GetDeclaredField("_arguments"); var errorAssemblies = failures.Where(x => x.Id == "CS0012").ToList(); foreach (var ass in errorAssemblies) { object info = infoMember.Invoke(ass, null); object[] arguments = argumentField.GetValue(info) as object[]; var assemblyName = arguments[1].ToString(); file.ReferencedAssemblies.Add(assemblyName); } retry = true; } if (retry) { goto RETRY; } foreach (Diagnostic diagnostic in failures) { Console.Error.WriteLine(diagnostic.ToString()); } Console.Error.WriteLine($"Exit Code = -1; \"Failed to compile\""); #if DEBUG Console.ReadKey(); #endif Environment.Exit(-1); } else { ms.Seek(0, SeekOrigin.Begin); file.LoadedAssembly = AssemblyLoadContext.Default.LoadFromStream(ms); } } ////Remove all get_, set_, k__BackingFields, and .cctor runtime members. file.Members = file.LoadedAssembly.DefinedTypes.SelectMany(x => x.DeclaredMembers.Where(y => !y.Name.Contains("k__BackingField"))).ToList(); file.Members = file.Members.Where(x => { if (x is MethodInfo mi) { return(!mi.Attributes.HasFlag(MethodAttributes.SpecialName)); } else if (x is ConstructorInfo ci) { return(!ci.Attributes.HasFlag(MethodAttributes.SpecialName)); } return(true); }).ToList(); return(file); }
private SyntaxTree renameProgramClass(SyntaxTree tree) { ClassDeclarationSyntax mainClass = this.getTopLevelClasses(tree).First(); SyntaxTree newTree = null; if (mainClass != null) { SyntaxToken newIdentifier = SyntaxFactory.Identifier(SESCriptBuilderInstance.ProgramName); SyntaxList <MemberDeclarationSyntax> members = mainClass.Members; if (members != null && members.Count() > 0) { SyntaxList <MemberDeclarationSyntax> newMembers = new SyntaxList <MemberDeclarationSyntax>(); foreach (MemberDeclarationSyntax member in members) { MemberDeclarationSyntax newMember = member; if (member.GetType() == typeof(ConstructorDeclarationSyntax)) { ConstructorDeclarationSyntax cons = member as ConstructorDeclarationSyntax; SyntaxToken identifier = cons.Identifier; if (identifier != null) { newMember = SyntaxFactory.ConstructorDeclaration(cons.AttributeLists, cons.Modifiers, newIdentifier, cons.ParameterList, cons.Initializer, cons.Body, cons.ExpressionBody, cons.SemicolonToken); } } newMembers = newMembers.Add(newMember); } members = newMembers; } ClassDeclarationSyntax newClass = mainClass.WithIdentifier(newIdentifier).WithMembers(members); if (newClass != null) { IEnumerable <NamespaceDeclarationSyntax> namespaces = tree.GetRootAsync().Result.DescendantNodes().OfType <NamespaceDeclarationSyntax>(); CompilationUnitSyntax newComp = null; CompilationUnitSyntax oldComp = tree.GetCompilationUnitRoot(); SyntaxList <MemberDeclarationSyntax> newClassMembers = new SyntaxList <MemberDeclarationSyntax>(); newClassMembers = newClassMembers.Add(newClass); if (namespaces != null && namespaces.Count() > 0) { NamespaceDeclarationSyntax ns = namespaces.First(); if (ns != null) { NamespaceDeclarationSyntax newNs = ns.WithMembers(newClassMembers); SyntaxList <MemberDeclarationSyntax> newNsMembers = new SyntaxList <MemberDeclarationSyntax>(); newNsMembers = newNsMembers.Add(newNs); newComp = oldComp.WithMembers(newNsMembers); } } else { newComp = oldComp.WithMembers(newClassMembers); } if (newComp != null) { newTree = newComp.SyntaxTree; } } } return(newTree); }
private void DownloadWSDL() { NamespaceDeclarationSyntax ns = NamespaceDeclaration(IdentifierName(nameSpace)); DiscoveryClientDocument = DiscoveryClient.DiscoverAny(_endpointUri.ToString()); DiscoveryClient.ResolveAll(); DiscoveryContractReference = DiscoveryClientDocument.References[0] as ContractReference; var schemas = new XmlSchemaSet(); foreach (DictionaryEntry entry in DiscoveryClient.References) { if (!(entry.Value is SchemaReference discoveryReference)) { continue; } foreach (XmlSchemaObject schemaObject in discoveryReference.Schema.Items) { DiscoveryClientReferencesElements.Add(schemaObject); } schemas.Add(discoveryReference.Schema.TargetNamespace, discoveryReference.Ref); } var headers = DiscoveryContractReference.Contract.Messages["headers"]; var ms = new MemoryStream(); var writer = new StringWriter(); var generator = new Generator() { OutputWriter = new GeneratorOutput(writer), CollectionType = typeof(System.Collections.Generic.List <>), Log = s => Console.Out.WriteLine(s), NamespacePrefix = nameSpace, NamingScheme = NamingScheme.Direct, UniqueTypeNamesAcrossNamespaces = true, GenerateNullables = true, CollectionSettersMode = CollectionSettersMode.PublicWithoutConstructorInitialization, EntityFramework = true, TypeVisitor = (type, model) => { if ((!type.IsClass) && !(type.IsInterface)) { return; } foreach (CodeAttributeDeclaration attribute in type.CustomAttributes) { if (attribute.Name != "System.Xml.Serialization.XmlRootAttribute") { continue; } foreach (CodeAttributeArgument argument in attribute.Arguments) { if (argument.Name != "") { continue; } var partname = (argument.Value as CodePrimitiveExpression).Value.ToString(); try { headers.FindPartByName(partname); type.BaseTypes.Add(new CodeTypeReference("SimpleSOAPClient.Models.SoapHeader")); return; } catch { } } } } }; generator.Generate(schemas); var tree = CSharpSyntaxTree.ParseText(writer.ToString()); var root = tree.GetRoot(); if (!(root is CompilationUnitSyntax compilationUnit)) { throw new Exception("XmlSchemaClassGenerator did not produce a valid CSharp code file"); } ns = compilationUnit.Members.First() as NamespaceDeclarationSyntax; if (ns == null) { throw new Exception("XmlSchemaClassGenerator did not produce a valid CSharp namespace as the first node"); } DiscoveryContractReference.Contract.Types.Schemas.Compile(null, true); foreach (Binding binding in DiscoveryContractReference.Contract.Bindings) { var portClass = ClassDeclaration(string.Format("{0}Client", binding.Type.Name)).WithModifiers(TokenList(new[] { Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.PartialKeyword) })); foreach (OperationBinding operation in binding.Operations) { var inputMessage = DiscoveryContractReference.Contract.Messages[operation.Input.Name]; var outputMessage = DiscoveryContractReference.Contract.Messages[operation.Output.Name]; var inputPart = inputMessage.FindPartByName("parameters"); var outputPart = outputMessage.FindPartByName("parameters"); var inputElement = DiscoveryClientReferencesElements.Elements[inputPart.Element.Name]; var outputElement = DiscoveryClientReferencesElements.Elements[outputPart.Element.Name]; var inputType = string.Format("{0}.{1}", nameSpace, inputElement.SchemaTypeName.Name); var outputType = string.Format("{0}.{1}", nameSpace, outputElement.SchemaTypeName.Name); var methodName = QualifiedName(IdentifierName("System.Threading.Tasks"), GenericName(Identifier("Task")).WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList <TypeSyntax>(ParseTypeName(GetAliasedType(outputType)))))); var operationMethod = MethodDeclaration(methodName, Identifier(operation.Name)); var headerCollectionDeclaration = VariableDeclaration( ArrayType(IdentifierName("SimpleSOAPClient.Models.SoapHeader")).WithRankSpecifiers( SingletonList <ArrayRankSpecifierSyntax>( ArrayRankSpecifier( SingletonSeparatedList <ExpressionSyntax>( OmittedArraySizeExpression()))))); var headerVariable = VariableDeclarator(Identifier("headers")); var headerArrayInitializer = InitializerExpression(SyntaxKind.ArrayInitializerExpression); SyntaxList <StatementSyntax> bodyStatements = new SyntaxList <StatementSyntax>(); foreach (ServiceDescriptionFormatExtension extension in operation.Input.Extensions) { ParameterSyntax parameter; if (extension is SoapHeaderBinding header) { var headerMessage = DiscoveryContractReference.Contract.Messages[header.Message.Name]; var headerPart = headerMessage.FindPartByName(header.Part); var headerElement = DiscoveryClientReferencesElements.Elements[headerPart.Element.Name]; var headerType = string.Format("{0}.{1}", nameSpace, headerElement.SchemaTypeName.Name); parameter = Parameter(Identifier(header.Part)).WithType(ParseTypeName(GetAliasedType(headerType))); operationMethod = operationMethod.AddParameterListParameters(parameter); headerArrayInitializer = headerArrayInitializer.AddExpressions(IdentifierName(header.Part)); } else if (extension is SoapBodyBinding body) { parameter = Parameter(Identifier("request")).WithType(ParseTypeName(GetAliasedType(inputType))); operationMethod = operationMethod.AddParameterListParameters(parameter); } } headerVariable = headerVariable.WithInitializer(EqualsValueClause(headerArrayInitializer)); headerCollectionDeclaration = headerCollectionDeclaration.AddVariables(headerVariable); var headerCollectionBlock = LocalDeclarationStatement(headerCollectionDeclaration); bodyStatements = bodyStatements.Add(headerCollectionBlock); bodyStatements = bodyStatements.Add(EmptyStatement().WithSemicolonToken(MissingToken(SyntaxKind.SemicolonToken))); var invocationMemberAccessExpression = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("SimpleSOAPClient.Models"), IdentifierName("SimpleSOAPClientBase")); var memberAccessExpression = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, invocationMemberAccessExpression, GenericName(Identifier("Send")).WithTypeArgumentList(TypeArgumentList(SeparatedList <TypeSyntax>(new SyntaxNodeOrToken[] { IdentifierName(GetAliasedType(inputType)), Token(SyntaxKind.CommaToken), IdentifierName(GetAliasedType(outputType)) })))); var arguments = ArgumentList(SeparatedList <ArgumentSyntax>(new SyntaxNodeOrToken[] { Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(operation.Name))), Token(SyntaxKind.CommaToken), Argument(IdentifierName("request")), Token(SyntaxKind.CommaToken), Argument(IdentifierName("headers")) })); var invocationExpression = InvocationExpression(memberAccessExpression).WithArgumentList(arguments); var awaitExpression = AwaitExpression(invocationExpression); bodyStatements = bodyStatements.Add(ReturnStatement(awaitExpression)); operationMethod = operationMethod.WithBody(Block(bodyStatements)); operationMethod = operationMethod.WithModifiers(new SyntaxTokenList(new SyntaxToken[] { Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.AsyncKeyword) })); portClass = portClass.AddMembers(operationMethod); } ns = ns.AddMembers(portClass); } var newWriter = new StreamWriter("NewSimpleSoapReference.cs", false, Encoding.UTF8); ns.NormalizeWhitespace() .WriteTo(newWriter); newWriter.Flush(); newWriter.Close(); }
Document PerformAction(Document document, SemanticModel model, SyntaxNode root, PropertyDeclarationSyntax propertyDeclaration, bool needsSetter) { AccessorDeclarationSyntax accessor = null; PropertyDeclarationSyntax newProp = null; if (needsSetter) { accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration); var getter = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(m => m.IsKind(SyntaxKind.GetAccessorDeclaration)); if (getter == null) { //get; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); } else { var getField = ReplacePropertyWithBackingFieldWithAutoPropertyCodeRefactoringProvider.ScanGetter(model, getter); if (getField == null && getter.Body == null) { //get; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)).WithTrailingTrivia(getter.GetTrailingTrivia()); } else if (getField == null || getField.IsReadOnly) { //readonly or no field can be found accessor = accessor.WithBody(GetNotImplementedBlock()); } else { //now we add a 'field = value'. accessor = accessor.WithBody(SyntaxFactory.Block( SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(getField.Name), SyntaxFactory.IdentifierName("value"))))); } } newProp = propertyDeclaration.WithAccessorList(propertyDeclaration.AccessorList.AddAccessors(accessor)); } else { accessor = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration); var setter = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(m => m.IsKind(SyntaxKind.SetAccessorDeclaration)); var accessorDeclList = new SyntaxList <AccessorDeclarationSyntax>(); if (setter == null) { //set; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)); } else { var setField = ReplacePropertyWithBackingFieldWithAutoPropertyCodeRefactoringProvider.ScanSetter(model, setter); if (setField == null && setter.Body == null) { //set; accessor = accessor.WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken)).WithTrailingTrivia(setter.GetTrailingTrivia()); } else if (setField == null) { //no field can be found accessor = accessor.WithBody(GetNotImplementedBlock()); } else { //now we add a 'return field;'. accessor = accessor.WithBody(SyntaxFactory.Block( SyntaxFactory.ReturnStatement(SyntaxFactory.IdentifierName(setField.Name)))); } accessorDeclList = accessorDeclList.Add(propertyDeclaration.AccessorList.Accessors.First(m => m.IsKind(SyntaxKind.SetAccessorDeclaration))); } accessorDeclList = accessorDeclList.Insert(0, accessor); var accessorList = SyntaxFactory.AccessorList(accessorDeclList); newProp = propertyDeclaration.WithAccessorList(accessorList); } var newRoot = root.ReplaceNode((SyntaxNode)propertyDeclaration, newProp).WithAdditionalAnnotations(Formatter.Annotation); return(document.WithSyntaxRoot(newRoot)); }
public SyntaxList <MemberDeclarationSyntax> AddMember(SyntaxList <MemberDeclarationSyntax> members) { return(members.Add(_class)); }
private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { var documentRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode syntax = documentRoot.FindNode(diagnostic.Location.SourceSpan); if (syntax == null) { return(document); } MethodDeclarationSyntax methodDeclarationSyntax = syntax.FirstAncestorOrSelf <MethodDeclarationSyntax>(); DelegateDeclarationSyntax delegateDeclarationSyntax = syntax.FirstAncestorOrSelf <DelegateDeclarationSyntax>(); if (methodDeclarationSyntax == null && delegateDeclarationSyntax == null) { return(document); } DocumentationCommentTriviaSyntax documentationComment = methodDeclarationSyntax?.GetDocumentationCommentTriviaSyntax() ?? delegateDeclarationSyntax?.GetDocumentationCommentTriviaSyntax(); if (documentationComment == null) { return(document); } SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); bool isTask; bool isAsynchronousTestMethod; if (methodDeclarationSyntax != null) { isTask = IsTaskReturningMethod(semanticModel, methodDeclarationSyntax, cancellationToken); isAsynchronousTestMethod = isTask && IsAsynchronousTestMethod(semanticModel, methodDeclarationSyntax, cancellationToken); } else { isTask = IsTaskReturningMethod(semanticModel, delegateDeclarationSyntax, cancellationToken); isAsynchronousTestMethod = false; } XmlNodeSyntax returnsElement = documentationComment.Content.GetFirstXmlElement(XmlCommentHelper.ReturnsXmlTag) as XmlNodeSyntax; if (returnsElement != null && !isTask) { // This code fix doesn't know how to do anything more than document Task-returning methods. return(document); } SyntaxList <XmlNodeSyntax> content = XmlSyntaxFactory.List(); if (isTask) { content = content.Add(XmlSyntaxFactory.Text("A ")); content = content.Add(XmlSyntaxFactory.SeeElement(SyntaxFactory.TypeCref(SyntaxFactory.ParseTypeName("global::System.Threading.Tasks.Task"))).WithAdditionalAnnotations(Simplifier.Annotation)); string operationKind = isAsynchronousTestMethod ? "unit test" : "operation"; content = content.Add(XmlSyntaxFactory.Text($" representing the asynchronous {operationKind}.")); // wrap the generated content in a <placeholder> element for review. content = XmlSyntaxFactory.List(XmlSyntaxFactory.PlaceholderElement(content)); } // Try to replace an existing <returns> element if the comment contains one. Otherwise, add it as a new element. SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode newRoot; if (returnsElement != null) { XmlEmptyElementSyntax emptyElement = returnsElement as XmlEmptyElementSyntax; if (emptyElement != null) { XmlElementSyntax updatedReturns = XmlSyntaxFactory.Element(XmlCommentHelper.ReturnsXmlTag, content) .WithLeadingTrivia(returnsElement.GetLeadingTrivia()) .WithTrailingTrivia(returnsElement.GetTrailingTrivia()); newRoot = root.ReplaceNode(returnsElement, updatedReturns); } else { XmlElementSyntax updatedReturns = ((XmlElementSyntax)returnsElement).WithContent(content); newRoot = root.ReplaceNode(returnsElement, updatedReturns); } } else { string newLineText = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp); returnsElement = XmlSyntaxFactory.Element(XmlCommentHelper.ReturnsXmlTag, content); XmlNodeSyntax leadingNewLine = XmlSyntaxFactory.NewLine(newLineText); // HACK: The formatter isn't working when contents are added to an existing documentation comment, so we // manually apply the indentation from the last line of the existing comment to each new line of the // generated content. SyntaxTrivia exteriorTrivia = GetLastDocumentationCommentExteriorTrivia(documentationComment); if (!exteriorTrivia.Token.IsMissing) { leadingNewLine = leadingNewLine.ReplaceExteriorTrivia(exteriorTrivia); returnsElement = returnsElement.ReplaceExteriorTrivia(exteriorTrivia); } DocumentationCommentTriviaSyntax newDocumentationComment = documentationComment.WithContent( documentationComment.Content.InsertRange( documentationComment.Content.Count - 1, XmlSyntaxFactory.List(leadingNewLine, returnsElement))); newRoot = root.ReplaceNode(documentationComment, newDocumentationComment); } return(document.WithSyntaxRoot(newRoot)); }
private async Task <Document> ToStringInterpolationAsync(Document document, SyntaxNode node, CancellationToken cancellationToken) { if (!(node is LiteralExpressionSyntax stringLiteral)) { return(document); } var invocation = node.FindParent <InvocationExpressionSyntax>(); if (invocation == null) { return(document); } var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var type = semanticModel.GetTypeInfo(invocation).Type; if (!type.IsResourceBase()) { return(document); } var name = invocation.Expression is MemberAccessExpressionSyntax maes ? maes.Name as IdentifierNameSyntax : invocation.Expression is IdentifierNameSyntax ins ? ins : null; if (name == null) { return(document); } var validMethods = new[] { "Get", "GetList", "Post", "Put", "Delete" }; if (!validMethods.Contains(name.Identifier.Value)) { return(document); } var path = stringLiteral.Token.Value.ToString(); if (!path.Contains(":")) { return(document); } var parameters = Regex.Matches(path, ":[a-zA-Z0-9_-]*[^/]"); if (parameters.Count == 0) { return(document); } var syntaxList = new SyntaxList <InterpolatedStringContentSyntax>(); var literalIndex = 0; foreach (Match parameter in parameters) { var snakeCaseName = parameter.ToString() .Replace(":", ""); var propertyName = type.GetPropertyBySnakeCaseName(snakeCaseName) ?.Name ?? "[INVALID PROPERTY]"; var literalPart = path.Substring(literalIndex, parameter.Index - literalIndex); if (literalPart.Length > 0) { var token = SyntaxFactory.Token(SyntaxTriviaList.Empty, SyntaxKind.InterpolatedStringTextToken, literalPart, literalPart, SyntaxTriviaList.Empty); syntaxList = syntaxList.Add(SyntaxFactory.InterpolatedStringText(token)); } syntaxList = syntaxList.Add(SyntaxFactory.Interpolation(SyntaxFactory.IdentifierName(propertyName))); literalIndex = parameter.Index + parameter.Length; } if (literalIndex < path.Length) { var literalPart = path.Substring(literalIndex); var token = SyntaxFactory.Token(SyntaxTriviaList.Empty, SyntaxKind.InterpolatedStringTextToken, literalPart, literalPart, SyntaxTriviaList.Empty); syntaxList = syntaxList.Add(SyntaxFactory.InterpolatedStringText(token)); } var newNode = SyntaxFactory.InterpolatedStringExpression( SyntaxFactory.Token(SyntaxKind.InterpolatedStringStartToken), syntaxList); var root = await document.GetSyntaxRootAsync(cancellationToken); var newRoot = root.ReplaceNode(node, newNode); return(document.WithSyntaxRoot(newRoot)); }
private static async Task <Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken) { SyntaxNode root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); SyntaxNode enclosingNode = root.FindNode(diagnostic.Location.SourceSpan, findInsideTrivia: true); if (!(enclosingNode is XmlNodeSyntax xmlNodeSyntax)) { return(document); } XmlElementSyntax xmlElementSyntax = xmlNodeSyntax.FirstAncestorOrSelf <XmlElementSyntax>(); if (xmlElementSyntax == null) { return(document); } SyntaxToken startToken = root.FindToken(diagnostic.Location.SourceSpan.Start, findInsideTrivia: true); if (!(startToken.Parent is XmlNodeSyntax startNode) || startNode == xmlElementSyntax) { return(document); } while (startNode.Parent != xmlElementSyntax) { startNode = startNode.Parent as XmlNodeSyntax; if (startNode == null) { return(document); } } SyntaxToken stopToken = root.FindToken(diagnostic.Location.SourceSpan.End - 1, findInsideTrivia: true); if (!(stopToken.Parent is XmlNodeSyntax stopNode) || stopNode == xmlElementSyntax) { return(document); } while (stopNode.Parent != xmlElementSyntax) { stopNode = stopNode.Parent as XmlNodeSyntax; if (stopNode == null) { return(document); } } int startIndex = xmlElementSyntax.Content.IndexOf(startNode); int stopIndex = xmlElementSyntax.Content.IndexOf(stopNode); if (startIndex < 0 || stopIndex < 0) { return(document); } XmlElementSyntax paragraph = XmlSyntaxFactory.ParaElement(xmlElementSyntax.Content.Skip(startIndex).Take(stopIndex - startIndex + 1).ToArray()); SyntaxList <XmlNodeSyntax> leadingWhitespaceContent; SyntaxList <XmlNodeSyntax> trailingWhitespaceContent; paragraph = TrimWhitespaceContent(paragraph, out leadingWhitespaceContent, out trailingWhitespaceContent); SyntaxList <XmlNodeSyntax> newContent = XmlSyntaxFactory.List(); newContent = newContent.AddRange(xmlElementSyntax.Content.Take(startIndex)); newContent = newContent.AddRange(leadingWhitespaceContent); newContent = newContent.Add(paragraph); newContent = newContent.AddRange(trailingWhitespaceContent); newContent = newContent.AddRange(xmlElementSyntax.Content.Skip(stopIndex + 1)); return(document.WithSyntaxRoot(root.ReplaceNode(xmlElementSyntax, xmlElementSyntax.WithContent(newContent)))); }
/// <summary> /// The method with SplitTail needs to be splitted into two methods /// </summary> public MethodTransformerResult Transform(IMethodOrAccessorTransformationResult transformResult, ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata) { var methodResult = transformResult.AnalyzationResult; if (!methodResult.SplitTail) { return(MethodTransformerResult.Skip); } var methodNode = transformResult.Transformed; // Tail method body shall contain all statements after preconditions var skipStatements = methodResult.Preconditions.Count; // If a cancellation guard was generated we need to skip also that if (_analyzeConfiguration.UseCancellationTokens && _analyzeConfiguration.CancellationTokens.Guards && methodResult.CancellationTokenRequired) { skipStatements++; } var tailMethodBody = methodNode.Body .WithStatements(new SyntaxList <StatementSyntax>() .AddRange(methodNode.Body.Statements.Skip(skipStatements))); // Main method shall contain only preconditions and a call to the tail method var bodyStatements = new SyntaxList <StatementSyntax>() .AddRange(methodNode.Body.Statements.Take(skipStatements)); ParameterListSyntax tailCallParameterList; // TODO: handle name collisions var tailIdentifier = Identifier("Internal" + methodNode.Identifier.Value); // The transformed method has already the Async postfix MethodDeclarationSyntax tailMethod = null; LocalFunctionStatementSyntax tailFunction = null; if (_configuration.LocalFunctions) { tailFunction = LocalFunctionStatement( methodNode.ReturnType.WithoutLeadingTrivia(), tailIdentifier) .WithParameterList(ParameterList() .WithCloseParenToken(Token(TriviaList(), SyntaxKind.CloseParenToken, TriviaList(transformResult.EndOfLineTrivia)))) .AddAsync() .WithLeadingTrivia(transformResult.LeadingWhitespaceTrivia) .WithBody(tailMethodBody) .AppendIndent(transformResult.IndentTrivia.ToFullString()); // We do not need any parameter for the local function as we already have the parameters from the parent method tailCallParameterList = ParameterList(); } else { var tailMethodModifiers = TokenList( Token(TriviaList(transformResult.EndOfLineTrivia, transformResult.LeadingWhitespaceTrivia), SyntaxKind.PrivateKeyword, TriviaList(Space))); if (methodNode.Modifiers.Any(o => o.IsKind(SyntaxKind.StaticKeyword))) { tailMethodModifiers = tailMethodModifiers.Add(Token(TriviaList(), SyntaxKind.StaticKeyword, TriviaList(Space))); } tailMethod = methodNode .WithReturnType(methodNode.ReturnType.WithLeadingTrivia()) // Remove lead trivia in case the return type is the first node (eg. void Method()) .WithIdentifier(tailIdentifier) .WithModifiers(tailMethodModifiers) .AddAsync() .WithBody(tailMethodBody); // Tail call shall contain the cancellation token parameter tailCallParameterList = methodNode.ParameterList; } var tailCall = ReturnStatement( Token(TriviaList(transformResult.BodyLeadingWhitespaceTrivia), SyntaxKind.ReturnKeyword, TriviaList(Space)), IdentifierName(tailIdentifier).Invoke(tailCallParameterList), Token(TriviaList(), SyntaxKind.SemicolonToken, TriviaList(transformResult.EndOfLineTrivia)) ); bodyStatements = bodyStatements.Add(tailCall); // Append local function at the end for easier reading if (tailFunction != null) { bodyStatements = bodyStatements.Add(tailFunction); } methodNode = methodNode.WithBody(methodNode.Body .WithStatements(bodyStatements)); var result = MethodTransformerResult.Update(methodNode); if (tailMethod != null) { result.AddMethod(tailMethod); } return(result); }
private static Task <Document> RefactorAsync( Document document, ImmutableArray <FieldInfo> fieldInfos, TypeDeclarationSyntax typeDeclaration, CancellationToken cancellationToken) { SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members; HashSet <string> reservedNames = null; for (int i = 0; i < members.Count; i++) { if (!(members[i] is ConstructorDeclarationSyntax constructorDeclaration)) { continue; } if (constructorDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) { continue; } ParameterListSyntax parameterList = constructorDeclaration.ParameterList; if (parameterList == null) { continue; } BlockSyntax body = constructorDeclaration.Body; if (body == null) { continue; } SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters; reservedNames?.Clear(); ConstructorInitializerSyntax initializer = null; ArgumentListSyntax argumentList = null; var arguments = default(SeparatedSyntaxList <ArgumentSyntax>); if (constructorDeclaration.Initializer?.Kind() == SyntaxKind.ThisConstructorInitializer) { initializer = constructorDeclaration.Initializer; argumentList = initializer.ArgumentList; arguments = argumentList.Arguments; } SyntaxList <StatementSyntax> statements = body.Statements; foreach (FieldInfo fieldInfo in fieldInfos) { string parameterName = GetParameterName(fieldInfo.NameCamelCase, parameters, ref reservedNames); parameters = parameters.Add(Parameter(fieldInfo.Type.WithoutTrivia(), parameterName)); if (initializer != null) { arguments = arguments.Add(Argument(IdentifierName(parameterName))); } statements = statements.Add( SimpleAssignmentStatement( SimpleMemberAccessExpression(ThisExpression(), IdentifierName(fieldInfo.Name)).WithSimplifierAnnotation(), IdentifierName(parameterName)).WithFormatterAnnotation()); } parameterList = parameterList.WithParameters(parameters).WithFormatterAnnotation(); if (initializer != null) { initializer = initializer .WithArgumentList(argumentList.WithArguments(arguments)) .WithFormatterAnnotation(); } body = body.WithStatements(statements); constructorDeclaration = constructorDeclaration.Update( constructorDeclaration.AttributeLists, constructorDeclaration.Modifiers, constructorDeclaration.Identifier, parameterList, initializer, body, constructorDeclaration.SemicolonToken); members = members.ReplaceAt(i, constructorDeclaration); } TypeDeclarationSyntax newNode = typeDeclaration.WithMembers(members); return(document.ReplaceNodeAsync(typeDeclaration, newNode, cancellationToken)); }
private SyntaxList <MemberDeclarationSyntax> CreateProtectedConstructors() { var list = new SyntaxList <MemberDeclarationSyntax>(); //We implicitly have version //if( m_fields.Count > 0 ) { BaseMethodDeclarationSyntax cons = SF.ConstructorDeclaration(m_class.Identifier); cons = SU.AddKeyword(cons, SyntaxKind.ProtectedKeyword); var paramList = new SeparatedSyntaxList <ParameterSyntax>(); { var param = SF.Parameter(SF.Identifier("version")) .WithType(SF.IdentifierName("ulong")); paramList = paramList.Add(param); } foreach (var f in m_fields) { var param = SF.Parameter(f.Key.Identifier) .WithType(f.Value); paramList = paramList.Add(param); } cons = cons.WithParameterList(SF.ParameterList(paramList)); var block = SF.Block(); var assignments = new SyntaxList <StatementSyntax>(); foreach (var f in m_fields) { var statement = SF.ParseStatement($"this.{f.Key.Identifier} = {f.Key.Identifier};"); assignments = assignments.Add(statement); } block = block.WithStatements(assignments); cons = cons.WithBody(block); list = list.Add(cons); } { BaseMethodDeclarationSyntax cons = SF.ConstructorDeclaration(m_class.Identifier); cons = SU.AddKeyword(cons, SyntaxKind.ProtectedKeyword); var block = SF.Block(); cons = cons.WithBody(block); list = list.Add(cons); } return(list); }