示例#1
0
        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);
            }
        }
示例#2
0
        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());
            }
        }
示例#3
0
        /// <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()));
        }
示例#5
0
 public SimpleProperty(FieldDeclarationSyntax d)
 {
     Type           = d.Declaration.Type;
     Name           = d.Declaration.Variables[0].Identifier.Text;
     LeadingTrivia  = d.GetLeadingTrivia();
     TrailingTrivia = d.GetTrailingTrivia();
 }
示例#6
0
 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);
        }
示例#9
0
        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);
        }
示例#10
0
 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;
 }
示例#11
0
        /// <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());
        }
示例#12
0
        /// <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));
        }
示例#13
0
        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);
        }
示例#15
0
        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);
        }
示例#17
0
        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);
        }
示例#18
0
            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);
            }
示例#19
0
            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);
            }
示例#20
0
            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));
        }