private async Task <Document> IntroduceGuardAsync(Document document, SyntaxNode node, HowToGuard g, CancellationToken cancellationToken)
        {
            // + if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent(targetContainingType))
            // {
            //     old-statement
            // + }
            try
            {
                var oldStatement     = node.FirstAncestorOrSelf <StatementSyntax>();
                var oldLeadingTrivia = oldStatement.GetLeadingTrivia();

                var conditionReceiver = SyntaxFactory.ParseName($"Windows.Foundation.Metadata.ApiInformation.{g.KindOfCheck}").WithAdditionalAnnotations(Simplifier.Annotation);
                ArgumentListSyntax conditionArgument = null;

                if (g.MemberToCheck == null)
                {
                    var conditionString1 = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(g.TypeToCheck));
                    conditionArgument = SyntaxFactory.ArgumentList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Argument(conditionString1)));
                }
                else
                {
                    var conditionString1 = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(g.TypeToCheck));
                    var conditionString2 = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(g.MemberToCheck));
                    var conditionInt3    = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(g.ParameterCountToCheck ?? 0));

                    IEnumerable <ArgumentSyntax> conditions = null;

                    if (g.ParameterCountToCheck.HasValue)
                    {
                        conditions = new ArgumentSyntax[] { SyntaxFactory.Argument(conditionString1), SyntaxFactory.Argument(conditionString2), SyntaxFactory.Argument(conditionInt3) };
                    }
                    else
                    {
                        conditions = new ArgumentSyntax[] { SyntaxFactory.Argument(conditionString1), SyntaxFactory.Argument(conditionString2) };
                    }

                    conditionArgument = SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(conditions));
                }

                var condition = SyntaxFactory.InvocationExpression(conditionReceiver, conditionArgument);

                var thenStatements = SyntaxFactory.Block(oldStatement.WithoutLeadingTrivia());
                var ifStatement    = SyntaxFactory.IfStatement(condition, thenStatements).WithLeadingTrivia(oldLeadingTrivia).WithAdditionalAnnotations(Formatter.Annotation);

                var oldRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

                var newRoot = oldRoot.ReplaceNode(oldStatement, ifStatement);

                return(document.WithSyntaxRoot(newRoot));
            }
            catch
            {
            }

            return(document);
        }
예제 #2
0
        /// <summary>
        /// returns instance of <see cref="HowToGuard"/> for <see cref="ISymbol"/>
        /// </summary>
        /// <param name="target">instance of <see cref="ISymbol"/></param>
        /// <returns>instance of <see cref="HowToGuard"/></returns>
        public static HowToGuard GetGuardForSymbol(ISymbol target)
        {
            var plat = Analyzer.GetPlatformForSymbol(target);

            switch (plat.Kind)
            {
            case PlatformKind.ExtensionSDK:
                return(new HowToGuard()
                {
                    TypeToCheck = target.Kind == SymbolKind.NamedType ? target.ToDisplayString() : target.ContainingType.ToDisplayString(),
                    KindOfCheck = "IsTypePresent"
                });

            case PlatformKind.Uwp:
                if (target.Kind == SymbolKind.NamedType)
                {
                    return(new HowToGuard()
                    {
                        TypeToCheck = target.ToDisplayString(),
                        KindOfCheck = "IsTypePresent"
                    });
                }
                else
                {
                    var g = new HowToGuard
                    {
                        TypeToCheck = target.ContainingType.ToDisplayString()
                    };

                    var d0 = Analyzer.GetUniversalApiAdditions(Analyzer.N0DifferencesRes);
                    var d1 = Analyzer.GetUniversalApiAdditions(Analyzer.N1DifferencesRes);

                    if (!d0.TryGetValue(g.TypeToCheck, out List <NewMember> newMembers))
                    {
                        d1.TryGetValue(g.TypeToCheck, out newMembers);
                    }

                    if (newMembers == null)
                    {
                        throw new InvalidOperationException("oops! expected this UWP version API to be in the dictionary of new things");
                    }

                    g.MemberToCheck = target.Name;

                    if (target.Kind == SymbolKind.Field)
                    {
                        // the only fields in WinRT are enum fields
                        g.KindOfCheck = "IsEnumNamedValuePresent";
                    }
                    else if (target.Kind == SymbolKind.Event)
                    {
                        g.KindOfCheck = "IsEventPresent";
                    }
                    else if (target.Kind == SymbolKind.Property)
                    {
                        // TODO: if SDK starts introducing additional accessors on properties, we'll have to change this
                        g.KindOfCheck = "IsPropertyPresent";
                    }
                    else if (target.Kind == SymbolKind.Method)
                    {
                        g.KindOfCheck = "IsMethodPresent";

                        if (target.Kind == SymbolKind.Method && plat.ByParameterCount)
                        {
                            g.ParameterCountToCheck = (target as IMethodSymbol).Parameters.Length;
                        }
                    }

                    return(g);
                }

            default:
                throw new InvalidOperationException("oops! don't know why I was asked to check something that's fine");
            }
        }