public static IEnumerable <AttributeListSyntax> SplitAttributes(AttributeListSyntax attributeList)
        {
            if (attributeList == null)
            {
                throw new ArgumentNullException(nameof(attributeList));
            }

            SeparatedSyntaxList <AttributeSyntax> attributes = attributeList.Attributes;

            for (int i = 0; i < attributes.Count; i++)
            {
                AttributeListSyntax list = AttributeList(attributes[i]);

                if (i == 0)
                {
                    list = list.WithLeadingTrivia(attributeList.GetLeadingTrivia());
                }

                if (i == attributes.Count - 1)
                {
                    list = list.WithTrailingTrivia(attributeList.GetTrailingTrivia());
                }

                yield return(list.WithFormatterAnnotation());
            }
        }
        public static IEnumerable <AttributeListSyntax> SplitAttributes(AttributeListSyntax attributeList)
        {
            if (attributeList == null)
            {
                throw new ArgumentNullException(nameof(attributeList));
            }

            for (int i = 0; i < attributeList.Attributes.Count; i++)
            {
                AttributeListSyntax list = SyntaxFactory.AttributeList(
                    SyntaxFactory.SingletonSeparatedList(attributeList.Attributes[i]));

                if (i == 0)
                {
                    list = list.WithLeadingTrivia(attributeList.GetLeadingTrivia());
                }

                if (i == attributeList.Attributes.Count - 1)
                {
                    list = list.WithTrailingTrivia(attributeList.GetTrailingTrivia());
                }

                yield return(list);
            }
        }
        public static AttributeListSyntax JoinAttributes(IList <AttributeListSyntax> lists)
        {
            AttributeListSyntax list = lists[0];

            for (int i = 1; i < lists.Count; i++)
            {
                list = list.AddAttributes(lists[i].Attributes.ToArray());
            }

            return(list
                   .WithLeadingTrivia(lists[0].GetLeadingTrivia())
                   .WithTrailingTrivia(lists.Last().GetTrailingTrivia()));
        }
        public static AttributeListSyntax MergeAttributes(AttributeListSyntax[] lists)
        {
            AttributeListSyntax list = lists[0];

            for (int i = 1; i < lists.Length; i++)
            {
                list = list.AddAttributes(lists[i].Attributes.ToArray());
            }

            return(list
                   .WithLeadingTrivia(lists[0].GetLeadingTrivia())
                   .WithTrailingTrivia(lists.Last().GetTrailingTrivia())
                   .WithFormatterAnnotation());
        }
            public override SyntaxNode VisitAttributeList(AttributeListSyntax attributeListNode)
            {
                _cancellationToken.ThrowIfCancellationRequested();

                if (_visitedAttributeListCounter < MaxVisitedAttributesCount)
                {
                    _visitedAttributeListCounter++;
                }

                var attributesToCheck  = attributeListNode.Attributes;
                var modifiedAttributes = new List <AttributeSyntax>(attributesToCheck.Count);

                foreach (AttributeSyntax attribute in attributesToCheck)
                {
                    _cancellationToken.ThrowIfCancellationRequested();

                    if (!IsAttributeToRemove(attribute))
                    {
                        modifiedAttributes.Add(attribute);
                    }
                }

                bool allPreviousAttributeListWereRemoved = _attributeListsRemovedCounter > 0 &&
                                                           _attributeListsRemovedCounter == (_visitedAttributeListCounter - 1);

                if (modifiedAttributes.Count == attributesToCheck.Count && !allPreviousAttributeListWereRemoved)
                {
                    return(attributeListNode);
                }
                else if (modifiedAttributes.Count == 0)
                {
                    if (_attributeListsRemovedCounter < MaxRemovedAttributesCount)
                    {
                        _attributeListsRemovedCounter++;
                    }

                    return(null);
                }

                AttributeListSyntax modifiedAttributeListNode = attributeListNode.WithAttributes(SyntaxFactory.SeparatedList(modifiedAttributes));

                if (allPreviousAttributeListWereRemoved)
                {
                    var trivia = modifiedAttributeListNode.GetLeadingTrivia().Prepend(SyntaxFactory.CarriageReturnLineFeed);
                    modifiedAttributeListNode = modifiedAttributeListNode.WithLeadingTrivia(trivia);
                }

                return(modifiedAttributeListNode);
            }
        public static AttributeListSyntax MergeAttributes(AttributeListSyntax[] attributeLists)
        {
            if (attributeLists == null)
            {
                throw new ArgumentNullException(nameof(attributeLists));
            }

            AttributeListSyntax attributeList = attributeLists[0];

            for (int i = 1; i < attributeLists.Length; i++)
            {
                attributeList = attributeList.AddAttributes(attributeLists[i].Attributes.ToArray());
            }

            return(attributeList
                   .WithLeadingTrivia(attributeLists.First().GetLeadingTrivia())
                   .WithTrailingTrivia(attributeLists.Last().GetTrailingTrivia()));
        }
        public static AttributeListSyntax MergeAttributes(AttributeListSyntax[] lists)
        {
            if (lists == null)
            {
                throw new ArgumentNullException(nameof(lists));
            }

            AttributeListSyntax list = lists[0];

            for (int i = 1; i < lists.Length; i++)
            {
                list = list.AddAttributes(lists[i].Attributes.ToArray());
            }

            return(list
                   .WithLeadingTrivia(lists[0].GetLeadingTrivia())
                   .WithTrailingTrivia(lists.Last().GetTrailingTrivia())
                   .WithFormatterAnnotation());
        }
        public static IEnumerable <AttributeListSyntax> SplitAttributeList(AttributeListSyntax attributeList)
        {
            SeparatedSyntaxList <AttributeSyntax> attributes = attributeList.Attributes;

            for (int i = 0; i < attributes.Count; i++)
            {
                AttributeListSyntax list = AttributeList(attributes[i]);

                if (i == 0)
                {
                    list = list.WithLeadingTrivia(attributeList.GetLeadingTrivia());
                }

                if (i == attributes.Count - 1)
                {
                    list = list.WithTrailingTrivia(attributeList.GetTrailingTrivia());
                }

                yield return(list);
            }
        }
        private T ApplyAction <T>(T node, ISymbol symbol, UpdateAction updateAction)
            where T : MemberDeclarationSyntax
        {
            var attributes = symbol.GetAttributes();
            var attribute  = attributes.SingleOrDefault(a => a.AttributeClass.ToString() == UsedNuGetSdkApiAttribute.FullName);

            T newNode = null;

            if (updateAction.AddAttribute && attribute == null)
            {
                if (node.AttributeLists.Count > 0)
                {
                    var leadingTrivia = node.GetLeadingTrivia();
                    var whitespace    = leadingTrivia.Last(t => t.IsKind(SyntaxKind.WhitespaceTrivia));
                    newNode = (T)node.AddAttributeLists(attributeListToAdd.WithLeadingTrivia(whitespace));
                }
                else
                {
                    var leadingTrivia = node.GetLeadingTrivia();
                    if (leadingTrivia.Count == 1 && leadingTrivia[0].IsKind(SyntaxKind.WhitespaceTrivia))
                    {
                        newNode =
                            (T)node.AddAttributeLists(attributeListToAdd.WithLeadingTrivia(leadingTrivia[0]));
                    }
                    else
                    {
                        var whitespaceTrivia = leadingTrivia.First(t => t.IsKind(SyntaxKind.WhitespaceTrivia));
                        newNode =
                            (T)node
                            .WithLeadingTrivia(whitespaceTrivia)
                            .AddAttributeLists(attributeListToAdd.WithLeadingTrivia(leadingTrivia));
                    }
                }
            }
            else if (!updateAction.AddAttribute && attribute != null)
            {
                var newAttributeLists = node.AttributeLists
                                        .Select(al =>
                {
                    AttributeSyntax toRemove = null;

                    foreach (var attr in al.Attributes)
                    {
                        var type = _semanticModel.GetTypeInfo(attr);
                        if (type.Type == null)
                        {
                            throw new NotSupportedException("AttributeSyntax's TypeInfo doesn't have a type");
                        }
                        if (type.Type.ToString() == UsedNuGetSdkApiAttribute.FullName)
                        {
                            toRemove = attr;
                            break;
                        }
                    }

                    if (toRemove == null)
                    {
                        return(al);
                    }

                    return(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(al.Attributes.Where(a => a != toRemove))));
                })
                                        .Where(al => al != null && al.Attributes.Count > 0);

                var leadingTrivia = node.GetLeadingTrivia();
                newNode = (T)node.WithAttributeLists(SyntaxFactory.List(newAttributeLists))
                          .WithLeadingTrivia(leadingTrivia);
            }

            if (newNode != null)
            {
                if (updateAction.Actioned)
                {
                    // already actioned?
                }
                updateAction.SetActioned();

                return(newNode);
            }
            else
            {
                return(node);
            }
        }
        public MethodTransformerResult Transform(IMethodOrAccessorTransformationResult transformResult,
                                                 ITypeTransformationMetadata typeMetadata, INamespaceTransformationMetadata namespaceMetadata)
        {
            var methodResult = transformResult.AnalyzationResult;

            if (!methodResult.Missing || !methodResult.Conversion.HasFlag(MethodConversion.ToAsync) || methodResult.Symbol.IsObsolete())
            {
                return(MethodTransformerResult.Skip);
            }
            var methodNode = transformResult.Transformed;

            var baseMethod = methodResult.RelatedMethods
                             .Where(o =>
                                    (methodResult.BaseOverriddenMethod != null && o.Symbol.Equals(methodResult.BaseOverriddenMethod)) ||
                                    methodResult.ImplementedInterfaces.Any(i => o.Symbol.Equals(i)))
                             .FirstOrDefault(o => o.AsyncCounterpartSymbol?.IsObsolete() == true);

            if (baseMethod == null)
            {
                return(MethodTransformerResult.Skip);
            }

            namespaceMetadata.AddUsing("System");
            AttributeListSyntax obsoleteAttribute = null;
            var          syntaxReference          = baseMethod.AsyncCounterpartSymbol.DeclaringSyntaxReferences.SingleOrDefault();
            SyntaxTrivia?documentationTrivia      = null;

            if (syntaxReference != null)
            {
                var baseMethodNode = syntaxReference.GetSyntax() as MethodDeclarationSyntax;
                obsoleteAttribute   = baseMethodNode?.AttributeLists.FirstOrDefault(o => o.Attributes.Count == 1 && o.Attributes.First().Name.ToString() == "Obsolete");
                obsoleteAttribute   = (AttributeListSyntax)_directiveRemover.VisitAttributeList(obsoleteAttribute);
                documentationTrivia = obsoleteAttribute.GetLeadingTrivia()
                                      .Select(o => o.IsKind(SyntaxKind.SingleLineDocumentationCommentTrivia) ? o : (SyntaxTrivia?)null)
                                      .FirstOrDefault(o => o.HasValue);
            }

            if (obsoleteAttribute == null)
            {
                obsoleteAttribute = AttributeList(SingletonSeparatedList(Attribute(IdentifierName("Obsolete"))))
                                    .WithOpenBracketToken(Token(TriviaList(transformResult.LeadingWhitespaceTrivia), SyntaxKind.OpenBracketToken, TriviaList()))
                                    .WithCloseBracketToken(Token(TriviaList(), SyntaxKind.CloseBracketToken, TriviaList(transformResult.EndOfLineTrivia)));
            }

            var inheritDocTrivia = Trivia(GetInheritdoc(transformResult.EndOfLineTrivia.ToFullString()));

            if (documentationTrivia.HasValue)
            {
                obsoleteAttribute = obsoleteAttribute.WithLeadingTrivia(obsoleteAttribute.GetLeadingTrivia()
                                                                        .Replace(documentationTrivia.Value, inheritDocTrivia));
            }
            else
            {
                // Append <inheritdoc />
                var leadingTrivia = obsoleteAttribute.GetLeadingTrivia();
                var trivias       = new List <SyntaxTrivia>();
                if (leadingTrivia.Count == 0 || !leadingTrivia.Last().IsKind(SyntaxKind.WhitespaceTrivia))
                {
                    trivias.Add(transformResult.LeadingWhitespaceTrivia);
                }

                trivias.Add(inheritDocTrivia);
                trivias.Add(transformResult.LeadingWhitespaceTrivia);
                obsoleteAttribute = obsoleteAttribute.WithLeadingTrivia(leadingTrivia.AddRange(trivias));
            }

            methodNode = methodNode
                         .WithLeadingTrivia(TriviaList(transformResult.LeadingWhitespaceTrivia))
                         .WithAttributeLists(methodNode.AttributeLists.Add(obsoleteAttribute));

            return(MethodTransformerResult.Update(methodNode));
        }
Beispiel #11
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));
            }