private async Task <Document> CreateConstructor(Document document, FieldDeclarationSyntax fieldDecl, CancellationToken c) { try { var varDecl = fieldDecl.Declaration.Variables.FirstOrDefault(); var fieldName = varDecl.Identifier.Text; var typeDecl = fieldDecl.Parent as TypeDeclarationSyntax; var ctorDecl = SyntaxFactory .ConstructorDeclaration(typeDecl.Identifier) .WithBody(SyntaxFactory.Block()) .WithLeadingTrivia(fieldDecl.GetLeadingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation, Simplifier.Annotation); var root = await document.GetSyntaxRootAsync(c); var newRoot = root.ReplaceNode(typeDecl, typeDecl.InsertNodesAfter(fieldDecl, new[] { ctorDecl })); typeDecl = newRoot.TypeWithName(typeDecl.Identifier.Text); fieldDecl = typeDecl.FieldWithName(fieldName); ctorDecl = typeDecl.GetConstructors().First(); newRoot = AddParameterToConstructor(newRoot, fieldDecl, ctorDecl); return(document.WithSyntaxRoot(newRoot)); } catch { return(document); } }
private static IEnumerable <FieldDeclarationSyntax> SplitFieldDeclaration(FieldDeclarationSyntax declaration) { SeparatedSyntaxList <VariableDeclaratorSyntax> variables = declaration.Declaration.Variables; FieldDeclarationSyntax declaration2 = declaration.WithoutTrivia(); for (int i = 0; i < variables.Count; i++) { FieldDeclarationSyntax newDeclaration = FieldDeclaration( declaration2.AttributeLists, declaration2.Modifiers, VariableDeclaration( declaration2.Declaration.Type, SingletonSeparatedList(variables[i]))); if (i == 0) { newDeclaration = newDeclaration.WithLeadingTrivia(declaration.GetLeadingTrivia()); } if (i == variables.Count - 1) { newDeclaration = newDeclaration.WithTrailingTrivia(declaration.GetTrailingTrivia()); } yield return(newDeclaration.WithFormatterAnnotation()); } }
/// <summary> /// Analyzes node. /// </summary> /// <param name="context">The context.</param> private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { FieldDeclarationSyntax node = context.Node as FieldDeclarationSyntax; // Only const. if (!node.Modifiers.Any(SyntaxKind.ConstKeyword)) { return; } DocumentationCommentTriviaSyntax commentTriviaSyntax = node .GetLeadingTrivia() .Select(o => o.GetStructure()) .OfType <DocumentationCommentTriviaSyntax>() .FirstOrDefault(); if (commentTriviaSyntax != null) { bool hasSummary = commentTriviaSyntax .ChildNodes() .OfType <XmlElementSyntax>() .Any(o => o.StartTag.Name.ToString().Equals(DocumentationHeaderHelper.Summary)); if (hasSummary) { return; } } VariableDeclaratorSyntax field = node.DescendantNodes().OfType <VariableDeclaratorSyntax>().First(); context.ReportDiagnostic(Diagnostic.Create(Rule, field.GetLocation())); }
/// <summary> /// Analyzes node. /// </summary> /// <param name="context">The context.</param> private static void AnalyzeNode(SyntaxNodeAnalysisContext context) { FieldDeclarationSyntax node = context.Node as FieldDeclarationSyntax; // Only const field. if (!node.Modifiers.Any(SyntaxKind.ConstKeyword)) { return; } if (Configuration.IsEnabledForPublicMembersOnly && PrivateMemberChecker.IsPrivateMember(node)) { return; } DocumentationCommentTriviaSyntax commentTriviaSyntax = node .GetLeadingTrivia() .Select(o => o.GetStructure()) .OfType <DocumentationCommentTriviaSyntax>() .FirstOrDefault(); if (commentTriviaSyntax != null && CommentHelper.HasComment(commentTriviaSyntax)) { return; } VariableDeclaratorSyntax field = node.DescendantNodes().OfType <VariableDeclaratorSyntax>().First(); context.ReportDiagnostic(Diagnostic.Create(Rule, field.GetLocation())); }
public SimpleProperty(FieldDeclarationSyntax d) { Type = d.Declaration.Type; Name = d.Declaration.Variables[0].Identifier.Text; LeadingTrivia = d.GetLeadingTrivia(); TrailingTrivia = d.GetTrailingTrivia(); }
public Field(FieldDeclarationSyntax d) { Type = d.Declaration.Type; Name = d.Declaration.Variables[0].Identifier.Text; LeadingTrivia = d.GetLeadingTrivia(); TrailingTrivia = d.GetTrailingTrivia(); _bits = FindBitFieldAttribute(d); }
public SimpleProperty(FieldDeclarationSyntax d, CodeGenerationOptions options) { Type = d.Declaration.Type; Name = d.Declaration.Variables[0].Identifier.Text; LeadingTrivia = d.GetLeadingTrivia(); TrailingTrivia = d.GetTrailingTrivia(); Options = options; }
private FieldDeclarationSyntax WithReadOnlyAdded(FieldDeclarationSyntax fieldDeclaration) { SyntaxTriviaList leadingTrivia = fieldDeclaration.GetLeadingTrivia(); fieldDeclaration = fieldDeclaration.WithLeadingTrivia(); fieldDeclaration = fieldDeclaration.AddModifiers(_readonlyModifier); fieldDeclaration = fieldDeclaration.WithLeadingTrivia(leadingTrivia); return(fieldDeclaration); }
private static SyntaxNode MakeSingleFieldReadonly(SyntaxNode root, FieldDeclarationSyntax fieldDeclaration) { var newFieldDeclaration = fieldDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword)) .WithTrailingTrivia(fieldDeclaration.GetTrailingTrivia()) .WithLeadingTrivia(fieldDeclaration.GetLeadingTrivia()) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(fieldDeclaration, newFieldDeclaration); return(newRoot); }
public MemberSyntax(FieldDeclarationSyntax field) { this.AttributeLists = field.AttributeLists; this.GetLeadingTrivia = () => field.GetLeadingTrivia(); this.ReplaceNode = (x, y) => field.ReplaceNode(x, y); this.WithoutLeadingTrivia = () => new MemberSyntax(field.WithoutLeadingTrivia()); this.WithLeadingTrivia = x => new MemberSyntax(field.WithLeadingTrivia(x)); this.AddAttributeLists = xs => new MemberSyntax(field.AddAttributeLists(xs)); this.Self = field; }
/// <summary> /// フィールド類取得 /// </summary> /// <param name="item">C#ソースを解析したインスタンス</param> /// <param name="index">インデックス数(半角スペース数)</param> /// <returns>TypeScriptのクラスフィールドに変換した文字列</returns> private string GetFieldDeclarationText(FieldDeclarationSyntax item, int index = 0) { var classObject = ClassObject.GetInstance(); var variable = item.Declaration.Variables[0]; // 前処理の場合はメソッドチェックと格納のみ if (classObject.IsPreAnalyze) { if (item.Modifiers.Any(modifier => modifier.Kind() == SyntaxKind.StaticKeyword)) { classObject.AddStaticMember(variable.Identifier.ValueText); } return(string.Empty); } var result = new StringBuilder(); //初期化処理を取得 var defineAssignmentAssertion = string.Empty; var createInitializeValue = classObject.GetCreateInitializeValue(item.Declaration.Type, variable.Initializer); if (string.IsNullOrEmpty(createInitializeValue)) { // 初期化情報がない場合は限定代入アサーションを設定 defineAssignmentAssertion = "!"; } // キーワード設定 var modifiers = new List <string>(); modifiers.Add(GetModifierText(item.Modifiers)); foreach (var modifer in item.Modifiers) { switch (modifer.Text) { case "const": modifiers.Add("readonly"); break; case "static": modifiers.Add("static"); break; } } result.Append(GetComments(item.GetLeadingTrivia().ToString())); result.Append($"{GetSpace(index)}{string.Join(' ',modifiers)} {variable.Identifier.ValueText}{defineAssignmentAssertion}: {classObject.GetTypeScriptType(item.Declaration.Type)}"); // 初期化処理を設定 result.Append(ReplaceMethodName(createInitializeValue)); result.AppendLine(";"); return(result.ToString()); }
/// <summary> /// Adds documentation header async. /// </summary> /// <param name="document">The document.</param> /// <param name="root">The root.</param> /// <param name="declarationSyntax">The declaration syntax.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>A Document.</returns> private async Task <Document> AddDocumentationHeaderAsync(Document document, SyntaxNode root, FieldDeclarationSyntax declarationSyntax, CancellationToken cancellationToken) { SyntaxTriviaList leadingTrivia = declarationSyntax.GetLeadingTrivia(); VariableDeclaratorSyntax field = declarationSyntax.DescendantNodes().OfType <VariableDeclaratorSyntax>().First(); string comment = CommentHelper.CreateFieldComment(field.Identifier.ValueText); DocumentationCommentTriviaSyntax commentTrivia = await Task.Run(() => DocumentationHeaderHelper.CreateOnlySummaryDocumentationCommentTrivia(comment), cancellationToken); SyntaxTriviaList newLeadingTrivia = leadingTrivia.Insert(leadingTrivia.Count - 1, SyntaxFactory.Trivia(commentTrivia)); FieldDeclarationSyntax newDeclaration = declarationSyntax.WithLeadingTrivia(newLeadingTrivia); SyntaxNode newRoot = root.ReplaceNode(declarationSyntax, newDeclaration); return(document.WithSyntaxRoot(newRoot)); }
public static FieldSpec LoadFromSyntaxNode(FieldDeclarationSyntax node) { FieldSpec fieldSpec = new FieldSpec(); fieldSpec.IsConst = node.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.ConstKeyword)); fieldSpec.IsReadonly = node.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.ReadOnlyKeyword)); fieldSpec.IsStatic = node.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.StaticKeyword)); // Null access will throw and be caught in our overall analyzer handler. VariableDeclarationSyntax variable = node.ChildNodes() .FirstOrDefault(childNode => childNode.IsKind(SyntaxKind.VariableDeclaration)) as VariableDeclarationSyntax; fieldSpec.Type = variable.Type.ToString(); fieldSpec.Name = DocumentedElement.LoadFromSyntaxNode(variable, node.GetLeadingTrivia()); return(fieldSpec); }
public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax field) { if (!field.Modifiers.Any(SyntaxKind.PrivateKeyword)) { return(field); } if (field.Modifiers.Any(SyntaxKind.ConstKeyword)) { return(field); } if (field.Modifiers.Any(SyntaxKind.StaticKeyword)) { return(field); } //var variables = new List<VariableDeclaratorSyntax>(); var variables = new List <VariableDeclaratorSyntax>(); foreach (var variable in field.Declaration.Variables) { var newVariable = variable.WithIdentifier(SyntaxFactory.Identifier(GetChangedName(variable.Identifier.ValueText)) .WithLeadingTrivia(variable.Identifier.LeadingTrivia) .WithTrailingTrivia(variable.Identifier.TrailingTrivia)) .WithLeadingTrivia(variable.GetLeadingTrivia()) .WithTrailingTrivia(variable.GetTrailingTrivia()); variables.Add(newVariable); } field = field .WithDeclaration(SyntaxFactory.VariableDeclaration(field.Declaration.Type, SyntaxFactory.SeparatedList(variables))) .WithLeadingTrivia(field.GetLeadingTrivia()) .WithTrailingTrivia(field.GetTrailingTrivia()); return(field); }
public FieldInfo(FieldDeclarationSyntax decl, IMemberContainer parent) { var variable = decl.Declaration.Variables.First(); if (decl.HasLeadingTrivia) { Documentation = GetDocumentation(decl.GetLeadingTrivia()); } Name = variable.Identifier.Text; ReturnType = decl.Declaration.Type.ToString(); _modifiers = decl.Modifiers .ParseModifiers() .WithDefaultVisibility(Modifier.Private); Parent = parent; Value = variable.Initializer?.Value?.ToString(); Signature = $"{ReturnType} {Name}"; if (Value != null) { Signature += " = " + Value; } Signature += ";"; }
public static SyntaxNode RemoveModifierFromNode(SyntaxNode node, SyntaxKind modifier) { //there seem to be no base classes to support WithModifiers. //dynamic modifiersNode = node; //return modifiersNode.WithModifiers(SyntaxFactory.TokenList(modifiersNode.Modifiers.Where(m => !m.IsKind(SyntaxKind.PrivateKeyword)))); MethodDeclarationSyntax methodNode = node as MethodDeclarationSyntax; if (methodNode != null) { return(methodNode.WithModifiers(SyntaxFactory.TokenList(methodNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(methodNode.GetLeadingTrivia())); } FieldDeclarationSyntax fieldNode = node as FieldDeclarationSyntax; if (fieldNode != null) { return(fieldNode.WithModifiers(SyntaxFactory.TokenList(fieldNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(fieldNode.GetLeadingTrivia())); } PropertyDeclarationSyntax propertyNode = node as PropertyDeclarationSyntax; if (propertyNode != null) { return(propertyNode.WithModifiers(SyntaxFactory.TokenList(propertyNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(propertyNode.GetLeadingTrivia())); } IndexerDeclarationSyntax indexerNode = node as IndexerDeclarationSyntax; if (indexerNode != null) { return(indexerNode.WithModifiers(SyntaxFactory.TokenList(indexerNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(indexerNode.GetLeadingTrivia())); } EventDeclarationSyntax eventNode = node as EventDeclarationSyntax; if (eventNode != null) { return(eventNode.WithModifiers(SyntaxFactory.TokenList(eventNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(eventNode.GetLeadingTrivia())); } ConstructorDeclarationSyntax ctrNode = node as ConstructorDeclarationSyntax; if (ctrNode != null) { return(ctrNode.WithModifiers(SyntaxFactory.TokenList(ctrNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(ctrNode.GetLeadingTrivia())); } OperatorDeclarationSyntax opNode = node as OperatorDeclarationSyntax; if (opNode != null) { return(opNode.WithModifiers(SyntaxFactory.TokenList(opNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(opNode.GetLeadingTrivia())); } ClassDeclarationSyntax classNode = node as ClassDeclarationSyntax; if (classNode != null) { return(classNode.WithModifiers(SyntaxFactory.TokenList(classNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(classNode.GetLeadingTrivia())); } InterfaceDeclarationSyntax interfaceNode = node as InterfaceDeclarationSyntax; if (interfaceNode != null) { return(interfaceNode.WithModifiers(SyntaxFactory.TokenList(interfaceNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(interfaceNode.GetLeadingTrivia())); } StructDeclarationSyntax structNode = node as StructDeclarationSyntax; if (structNode != null) { return(structNode.WithModifiers(SyntaxFactory.TokenList(structNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(structNode.GetLeadingTrivia())); } var enumNode = node as EnumDeclarationSyntax; if (enumNode != null) { return(enumNode.WithModifiers(SyntaxFactory.TokenList(enumNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(enumNode.GetLeadingTrivia())); } var delegateNode = node as DelegateDeclarationSyntax; if (delegateNode != null) { return(delegateNode.WithModifiers(SyntaxFactory.TokenList(delegateNode.Modifiers.Where(m => !m.IsKind(modifier)))) .WithLeadingTrivia(delegateNode.GetLeadingTrivia())); } return(node); }
public override Microsoft.CodeAnalysis.SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) { FieldDeclarationSyntax newNode = null; var parent = node.Parent; // Verify we have the correct context for the Field Declaration switch (_declarationLocation) { case SyntaxNode.FieldDeclarationLocation.Class: if (parent.Kind() != SyntaxKind.ClassBlock) { return(node); } break; case SyntaxNode.FieldDeclarationLocation.Module: if (parent.Kind() != SyntaxKind.ModuleBlock) { return(node); } break; case SyntaxNode.FieldDeclarationLocation.Structure: if (parent.Kind() != SyntaxKind.StructureBlock) { return(node); } break; } if (_targetPatternRegEx.Match(node.Declarators.First().Names.First().Identifier.ToString()).Success) { try { // Verify this expression is on line by itself. May not need to do this. // See if can have multiple FieldDeclarations on same line. if (VNCCA.Helpers.VB.IsOnLineByItself(node)) { // HACK(crhodes) // Figure out how to get Helpers to work here. Messages.AppendLine(String.Format("Removing {0} {1}", VNCCA.Helpers.VB.GetContainingContext(node, _configurationOptions), node.ToString())); if (_commentOutOnly) { List <SyntaxTrivia> newTrivia = new List <SyntaxTrivia>(); string existingLeadingTrivia = node.GetLeadingTrivia().ToString(); string existingLeadingTriviaFull = node.GetLeadingTrivia().ToFullString(); string existingTrailingTrivia = node.GetTrailingTrivia().ToString(); string existingTrailingTriviaFull = node.GetTrailingTrivia().ToFullString(); string startOfLineWhiteSpace = existingLeadingTrivia.Replace(System.Environment.NewLine, ""); newTrivia.Add(SyntaxFactory.CommentTrivia(existingLeadingTriviaFull)); newTrivia.Add(SyntaxFactory.CommentTrivia(VNCCA.Helpers.VB.MultiLineComment(_comment, startOfLineWhiteSpace))); newTrivia.Add(SyntaxFactory.CommentTrivia("' ")); newNode = node.WithLeadingTrivia(newTrivia); } else { // This removes the node newNode = null; } } else { Messages.AppendLine(String.Format("node: >{0}< >{1}< Is NOT OnLineByItself", node.ToString(), node.ToFullString())); newNode = node; } } catch (Exception ex) { Messages.AppendLine(string.Format("Ex:{0} InnerEx:{1}", ex.ToString(), ex.InnerException.ToString())); } } else { newNode = node; } return(newNode); }
PropertyDeclarationSyntax ConvertProperty(PropertyDeclarationSyntax propertyDeclaration, FieldDeclarationSyntax relatedField) { var leadingList = new SyntaxTriviaList(); if (relatedField.Declaration.Variables.Count == 1) { leadingList = leadingList.AddRange(relatedField.GetLeadingTrivia()); } var propertyDeclaration_GetLeadingTrivia = propertyDeclaration.GetLeadingTrivia(); if (leadingList.Any() && propertyDeclaration_GetLeadingTrivia.First().IsKind(SyntaxKind.EndOfLineTrivia) == false) { var endOfLine = relatedField.GetLeadingTrivia().FirstOrDefault(x => x.IsKind(SyntaxKind.EndOfLineTrivia)); if (endOfLine != null) { leadingList = leadingList.Add(endOfLine); } } leadingList = leadingList.AddRange(propertyDeclaration.GetLeadingTrivia()); var getNode = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(x => x.Keyword.IsKind(SyntaxKind.GetKeyword)); var setNode = propertyDeclaration.AccessorList.Accessors.FirstOrDefault(x => x.Keyword.IsKind(SyntaxKind.SetKeyword)); propertyDeclaration = propertyDeclaration .WithAccessorList ( propertyDeclaration.AccessorList.WithAccessors( new SyntaxList <AccessorDeclarationSyntax>() .Add( getNode .WithBody(null) .WithTrailingTrivia() .WithSemicolonToken( SyntaxFactory.ParseToken(";") .WithTrailingTrivia(SyntaxFactory.Space) ) .WithLeadingTrivia(SyntaxFactory.Space) ) .Add( setNode .WithBody(null) .WithTrailingTrivia() .WithSemicolonToken( SyntaxFactory.ParseToken(";") .WithTrailingTrivia(SyntaxFactory.Space) ) .WithLeadingTrivia(SyntaxFactory.Space) ) ) .WithOpenBraceToken(propertyDeclaration.AccessorList.OpenBraceToken.WithLeadingTrivia().WithTrailingTrivia()) .WithCloseBraceToken(propertyDeclaration.AccessorList.CloseBraceToken.WithLeadingTrivia()) ) .WithIdentifier(propertyDeclaration.Identifier.WithTrailingTrivia(SyntaxFactory.Space)) .WithLeadingTrivia(leadingList); return(propertyDeclaration); }
public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) { string fullName = SyntaxUtils.GetFullName(node); this.GetRemapInfo(fullName, out var listAttributes, node.Declaration.Type.ToString(), out string newType, out string newName); // ClangSharp mistakenly emits string[] for WCHAR[] Foo = "Bar". // Change it to string if (newType == null && node.Declaration.Type.ToString() == "string[]") { newType = "string"; } // Turn public static readonly Guids into string constants with an attribute // to signal language projections to turn them into Guid constants. Guid constants // aren't allowed in metadata, requiring us to surface them this way if (node.Modifiers.ToString() == "public static readonly" && node.Declaration.Type.ToString() == "Guid") { Guid guidVal = Guid.Empty; var varInitializer = node.Declaration.Variables.First().Initializer; if (varInitializer.Value is ObjectCreationExpressionSyntax objCreationSyntax) { var args = objCreationSyntax.ArgumentList.Arguments; if (args.Count == 11) { uint p0 = EncodeHelpers.ParseHex(args[0].ToString()); ushort p1 = (ushort)EncodeHelpers.ParseHex(args[1].ToString()); ushort p2 = (ushort)EncodeHelpers.ParseHex(args[2].ToString()); byte p3 = (byte)EncodeHelpers.ParseHex(args[3].ToString()); byte p4 = (byte)EncodeHelpers.ParseHex(args[4].ToString()); byte p5 = (byte)EncodeHelpers.ParseHex(args[5].ToString()); byte p6 = (byte)EncodeHelpers.ParseHex(args[6].ToString()); byte p7 = (byte)EncodeHelpers.ParseHex(args[7].ToString()); byte p8 = (byte)EncodeHelpers.ParseHex(args[8].ToString()); byte p9 = (byte)EncodeHelpers.ParseHex(args[9].ToString()); byte p10 = (byte)EncodeHelpers.ParseHex(args[10].ToString()); guidVal = new Guid(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10); } else if (objCreationSyntax.ArgumentList.Arguments.Count == 1) { // If this is an invalid format, remove the node if (!Guid.TryParse(objCreationSyntax.ArgumentList.Arguments[0].ToString(), out guidVal)) { return(null); } } } if (guidVal == Guid.Empty) { return(node); } node = node.RemoveNode(varInitializer, SyntaxRemoveOptions.KeepExteriorTrivia | SyntaxRemoveOptions.KeepEndOfLine); node = node.AddAttributeLists(EncodeHelpers.ConvertGuidToAttributeList(guidVal).WithLeadingTrivia(node.GetLeadingTrivia())); return(node); } node = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node); if (listAttributes != null) { foreach (var attrNode in listAttributes) { var attrListNode = SyntaxFactory.AttributeList( SyntaxFactory.SingletonSeparatedList <AttributeSyntax>(attrNode)); node = node.WithAttributeLists(node.AttributeLists.Add(attrListNode)); } } var firstVar = node.Declaration.Variables.First(); if (newName != null) { var newVar = SyntaxFactory.VariableDeclarator(SyntaxFactory.Identifier(newName)); node = node.ReplaceNode(firstVar, newVar); } if (newType != null) { node = node.WithDeclaration(node.Declaration.WithType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space))); } return(node); }
public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) { FieldDeclarationSyntax fieldDeclaration = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node); var typeInfo = model.GetTypeInfo(node.Declaration.Type); if (typeInfo.Type == null) { UdonSharpUtils.LogWarning($"Could not find symbol for {node}"); return(fieldDeclaration); } ITypeSymbol rootType = typeInfo.Type; while (rootType.TypeKind == TypeKind.Array) { rootType = ((IArrayTypeSymbol)rootType).ElementType; } if (rootType.TypeKind == TypeKind.Error || rootType.TypeKind == TypeKind.Unknown) { UdonSharpUtils.LogWarning($"Type {typeInfo.Type} for field '{fieldDeclaration.Declaration}' is invalid"); return(fieldDeclaration); } IFieldSymbol firstFieldSymbol = (IFieldSymbol)model.GetDeclaredSymbol(node.Declaration.Variables.First()); rootType = firstFieldSymbol.Type; // If the field is not serialized or is using Odin already, we don't need to do anything. if (!IsFieldSerializedWithoutOdin(firstFieldSymbol)) { return(fieldDeclaration); } // Getting the type may fail if it's a user type that hasn't compiled on the C# side yet. For now we skip it, but we should do a simplified check for jagged arrays if (!TypeSymbol.TryGetSystemType(rootType, out Type systemType)) { return(fieldDeclaration); } // If Unity can serialize the type, we're good if (UnitySerializationUtility.GuessIfUnityWillSerialize(systemType)) { return(fieldDeclaration); } // Common type that gets picked up as serialized but shouldn't be // todo: Add actual checking for if a type is serializable, which isn't consistent. Unity/System library types in large part are serializable but don't have the System.Serializable tag, but types outside those assemblies need the tag to be serialized. if (systemType == typeof(VRCPlayerApi) || systemType == typeof(VRCPlayerApi[])) { return(fieldDeclaration); } Modified = true; NameSyntax odinSerializeName = IdentifierName("VRC"); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("Udon")); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("Serialization")); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("OdinSerializer")); odinSerializeName = QualifiedName(odinSerializeName, IdentifierName("OdinSerialize")); // Somehow it seems like there's literally no decent way to maintain the indent on inserted code so we'll just inline the comment because Roslyn is dumb SyntaxTrivia commentTrivia = Comment(" /* UdonSharp auto-upgrade: serialization */ "); AttributeListSyntax newAttribList = AttributeList(SeparatedList(new [] { Attribute(odinSerializeName) })).WithTrailingTrivia(commentTrivia); SyntaxList <AttributeListSyntax> attributeList = fieldDeclaration.AttributeLists; if (attributeList.Count > 0) { SyntaxTriviaList trailingTrivia = attributeList.Last().GetTrailingTrivia(); trailingTrivia = trailingTrivia.Insert(0, commentTrivia); attributeList.Replace(attributeList[attributeList.Count - 1], attributeList[attributeList.Count - 1].WithoutTrailingTrivia()); newAttribList = newAttribList.WithTrailingTrivia(trailingTrivia); } else { newAttribList = newAttribList.WithLeadingTrivia(fieldDeclaration.GetLeadingTrivia()); fieldDeclaration = fieldDeclaration.WithoutLeadingTrivia(); } attributeList = attributeList.Add(newAttribList); return(fieldDeclaration.WithAttributeLists(attributeList)); }
private async Task <Solution> ChangeToReadOnlySpan(Document document, FieldDeclarationSyntax fieldDeclaration, CancellationToken cancellationToken) { var originalSolution = document.Project.Solution; var separatedTypes = new SeparatedSyntaxList <TypeSyntax>().Add((fieldDeclaration.Declaration.Type as ArrayTypeSyntax).ElementType); var typeListSyntax = SyntaxFactory.TypeArgumentList(separatedTypes); var readonlySpanType = SyntaxFactory.GenericName(SyntaxFactory.Identifier("ReadOnlySpan"), typeListSyntax); var equalsValueClauseSyntax = fieldDeclaration.Declaration.Variables.First().Initializer; var arrowExpressionSyntax = SyntaxFactory.ArrowExpressionClause(equalsValueClauseSyntax.Value); var propertyDeclaration = SyntaxFactory .PropertyDeclaration (fieldDeclaration.AttributeLists, new SyntaxTokenList(fieldDeclaration.Modifiers.Where(x => !x.IsKind(SyntaxKind.ReadOnlyKeyword))), readonlySpanType, null, fieldDeclaration.Declaration.Variables.First().Identifier, null, arrowExpressionSyntax, null); var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = root.ReplaceNode(fieldDeclaration, propertyDeclaration.WithLeadingTrivia(fieldDeclaration.GetLeadingTrivia()).WithSemicolonToken(fieldDeclaration.SemicolonToken).WithTrailingTrivia(fieldDeclaration.GetTrailingTrivia())); return(originalSolution.WithDocumentSyntaxRoot(document.Id, newRoot)); }