Ejemplo n.º 1
0
 public ConstantBindingContainer(
     IReadOnlyList <ITypeSymbol> bindFromTypes,
     ITypeSymbol constTypeSymbol,
     ArgumentSyntax constantSyntax,
     BindScopeEnum scope,
     ArgumentSyntax?whenArgumentClause
     ) : base(bindFromTypes, constTypeSymbol, scope, whenArgumentClause, constantSyntax, null)
 {
     ConstructorArguments            = new List <DetectedConstructorArgument>();
     NotBindConstructorArgumentTypes = new HashSet <ITypeSymbol>();
 }
Ejemplo n.º 2
0
 public ConstantBindingContainer(
     BindingContainerTypes types,
     ArgumentSyntax constantSyntax,
     BindScopeEnum scope,
     ExpressionStatementSyntax expressionNode,
     ArgumentSyntax?whenArgumentClause,
     IReadOnlyList <IDefinedSetting> settings
     ) : base(types, scope, expressionNode, whenArgumentClause, constantSyntax, settings, false)
 {
     ConstructorArguments = new List <DetectedMethodArgument>();
 }
Ejemplo n.º 3
0
        protected BaseBindingContainer(
            BindingContainerTypes types,
            BindScopeEnum scope,
            ExpressionStatementSyntax expressionNode,
            ArgumentSyntax?whenArgumentClause,
            ArgumentSyntax?constantSyntax,
            IReadOnlyList <IDefinedSetting> settings,
            bool isConventional
            )
        {
            if (types is null)
            {
                throw new ArgumentNullException(nameof(types));
            }

            if (scope == BindScopeEnum.Constant && constantSyntax is null)
            {
                throw new DpdtException(DpdtExceptionTypeEnum.InternalError, $"Misconfiguration between scope and constant syntax");
            }

            if (settings is null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            if (scope != BindScopeEnum.Constant && !(constantSyntax is null))
            {
                throw new DpdtException(DpdtExceptionTypeEnum.InternalError, $"Misconfiguration between scope and constant syntax");
            }

            _types                   = types;
            Scope                    = scope;
            ExpressionNode           = expressionNode;
            WhenArgumentClause       = whenArgumentClause;
            ConstantSyntax           = constantSyntax;
            _settings                = settings;
            IsConventional           = isConventional;
            UniqueUnstableIdentifier = Guid.NewGuid();

            var uniqueKey0 = expressionNode.SyntaxTree.FilePath.GetStringSha256Hash().SafeSubstring(0, 8);
            var uniqueKey1 = expressionNode.Span.Start;
            var uniqueKey2 = expressionNode.Span.End;
            var uniqueKey3 = types.BindToType.ToGlobalDisplayString().GetStringSha256Hash().SafeSubstring(0, 8);

            _uniqueKey = $"u{uniqueKey0}_{uniqueKey1}_{uniqueKey2}_{uniqueKey3}";
        }
Ejemplo n.º 4
0
        public BindingContainerWithInstance(
            BindingContainerTypes types,
            IReadOnlyList <DetectedMethodArgument> constructorArguments,
            BindScopeEnum scope,
            ExpressionStatementSyntax expressionNode,
            ArgumentSyntax?whenArgumentClause,
            IReadOnlyList <IDefinedSetting> settings,
            bool isConventional
            ) : base(types, scope, expressionNode, whenArgumentClause, null, settings, isConventional)
        {
            if (constructorArguments is null)
            {
                throw new ArgumentNullException(nameof(constructorArguments));
            }

            ConstructorArguments = constructorArguments;
        }
Ejemplo n.º 5
0
        private void ProcessConstant(
            ExpressionStatementSyntax expressionNode,
            GenericNameSyntax bindGenericNode,
            ArgumentSyntax?whenArgumentClause
            )
        {
            var genericNodes = expressionNode
                               .DescendantNodes()
                               .OfType <GenericNameSyntax>()
                               .ToList();


            var withScopeSyntax = expressionNode
                                  .DescendantNodes()
                                  .Where(s => s.GetText().ToString() == nameof(IToOrConstantBinding.WithConstScope))
                                  .First();

            var constTypeSymbol = (_semanticModel.GetSymbolInfo(withScopeSyntax).Symbol as IMethodSymbol) !.TypeArguments[0];

            var constantClause = DetermineArgumentSubClause(
                expressionNode,
                nameof(IToOrConstantBinding.WithConstScope)
                );

            if (constantClause is null)
            {
                throw new DpdtException(DpdtExceptionTypeEnum.InternalError, $"Cannot find constant clause");
            }

            var bindFromTypeSemantics = GetBindFromTypes(
                bindGenericNode
                );

            var bindingContainer = new ConstantBindingContainer(
                bindFromTypeSemantics,
                constTypeSymbol,
                constantClause,
                BindScopeEnum.Constant,
                whenArgumentClause
                );

            _bindingContainers.Add(bindingContainer);
        }
        public BindingContainerWithInstance(
            IReadOnlyList <ITypeSymbol> bindFromTypes,
            ITypeSymbol bindToType,
            IReadOnlyList <DetectedConstructorArgument> constructorArguments,
            BindScopeEnum scope,
            ArgumentSyntax?whenArgumentClause,
            ITypeSymbol?factoryPayloadType
            ) : base(bindFromTypes, bindToType, scope, whenArgumentClause, null, factoryPayloadType)
        {
            if (constructorArguments is null)
            {
                throw new ArgumentNullException(nameof(constructorArguments));
            }

            ConstructorArguments            = constructorArguments;
            NotBindConstructorArgumentTypes = new HashSet <ITypeSymbol>(
                constructorArguments
                .Where(ca => !ca.DefineInBindNode)
                .Select(ca => ca.Type !),
                new TypeSymbolEqualityComparer()
                );
        }
Ejemplo n.º 7
0
        private void ApppendSource(GeneratorExecutionContext context, StringBuilder sourceBuilder, GenerationDetails generateThis)
        {
            string propertyName  = generateThis.MethodNameNode.Identifier.ValueText;
            string dpMemberName  = propertyName + "Property";
            string dpkMemberName = propertyName + "PropertyKey";

            Accessibility dpAccess  = generateThis.FieldSymbol.DeclaredAccessibility;
            Accessibility dpkAccess = generateThis.FieldSymbol.DeclaredAccessibility;

            // If this is a DependencyPropertyKey, then we may need to create the corresponding DependencyProperty field.
            // We do this because it's proper to always have a DependencyProperty field & because the DependencyProperty
            // field is required when using TemplateBindings in XAML.
            if (generateThis.IsDpk)
            {
                ISymbol?dpMemberSymbol = generateThis.FieldSymbol.ContainingType.GetMembers(dpMemberName).FirstOrDefault();
                if (dpMemberSymbol != null)
                {
                    dpAccess = dpMemberSymbol.DeclaredAccessibility;
                }
                else
                {
                    dpAccess = Accessibility.Public;

                    // Something like...
                    //	public static readonly DependencyProperty FooProperty = FooPropertyKey.DependencyProperty;
                    sourceBuilder.Append($@"
		public static readonly DependencyProperty {dpMemberName} = {dpkMemberName}.DependencyProperty;"        );
                }
            }

            // Try to get the generic type argument (if it exists, this will be the type of the property).
            GeneratorOps.TryGetGenericTypeArgument(context, generateThis.MethodNameNode, out ITypeSymbol? genTypeArg);

            // We support 0, 1, or 2 arguments. Check for default value and/or flags arguments.
            //	(A) Gen.Foo<T>()
            //	(B) Gen.Foo(defaultValue)
            //	(C) Gen.Foo<T>(flags)
            //	(D) Gen.Foo(defaultValue, flags)
            // The first argument is either the default value or the flags.
            // Note: We do not support properties whose default value is `FrameworkPropertyMetadataOptions` because
            // it's a niche case that would add code complexity.
            ArgumentSyntax?defaultValueArgNode = null;
            ITypeSymbol?   typeOfFirstArg      = null;
            bool           hasFlags            = false;

            if (GeneratorOps.TryGetAncestor(generateThis.MethodNameNode, out InvocationExpressionSyntax? invocationExpressionNode))
            {
                var args = invocationExpressionNode.ArgumentList.Arguments;
                if (args.Count > 0)
                {
                    // If the first argument is the flags, then we generate (C); otherwise, we generate (B) or (D).
                    typeOfFirstArg = GetArgumentType(context, args[0]) ?? this.objTypeSymbol;
                    if (typeOfFirstArg.Equals(this.flagsTypeSymbol, SymbolEqualityComparer.Default))
                    {
                        hasFlags = true;
                    }
                    else
                    {
                        defaultValueArgNode = args[0];
                        hasFlags            = args.Count > 1;
                    }
                }
            }

            bool hasDefaultValue = defaultValueArgNode != null;

            // Determine the type of the property.
            // If there is a generic type argument, then use that; otherwise, use the type of the default value argument.
            // As a safety precaution - ensure that the generated code is always valid by defaulting to use `object`.
            // But really, if we were unable to get the type, that means the user's code doesn't compile anyhow.
            generateThis.PropertyType =
                genTypeArg
                ?? (hasDefaultValue ? typeOfFirstArg : null)
                ?? this.objTypeSymbol;

            generateThis.PropertyTypeName = generateThis.PropertyType.ToDisplayString();

            string genClassDecl;
            string?moreDox = null;

            if (generateThis.IsAttached)
            {
                string targetTypeName = "DependencyObject";

                if (generateThis.MethodNameNode.Parent is MemberAccessExpressionSyntax memberAccessExpr &&
                    memberAccessExpr.Expression is GenericNameSyntax genClassNameNode)
                {
                    genClassDecl = "GenAttached<__TTarget> where __TTarget : DependencyObject";

                    if (GeneratorOps.TryGetGenericTypeArgument(context, genClassNameNode, out ITypeSymbol? attachmentNarrowingType))
                    {
                        generateThis.AttachmentNarrowingType = attachmentNarrowingType;
                        targetTypeName = attachmentNarrowingType.ToDisplayString();
                        moreDox        = $@"<br/>This attached property is only for use with objects of type <typeparamref name=""__TTarget""/>.";
                    }
                }
                else
                {
                    genClassDecl = "GenAttached";
                }

                // Write the static get/set methods source code.
                string getterAccess = dpAccess.ToString().ToLower();
                string setterAccess = generateThis.IsDpk ? dpkAccess.ToString().ToLower() : getterAccess;
                string setterArg0   = generateThis.IsDpk ? dpkMemberName : dpMemberName;

                // Something like...
                //	public static int GetFoo(DependencyObject d) => (int)d.GetValue(FooProperty);
                //	private static void SetFoo(DependencyObject d, int value) => d.SetValue(FooPropertyKey);
                sourceBuilder.Append($@"
		{getterAccess} static {generateThis.PropertyTypeName} Get{propertyName}({targetTypeName} d) => ({generateThis.PropertyTypeName})d.GetValue({dpMemberName});
		{setterAccess} static void Set{propertyName}({targetTypeName} d, {generateThis.PropertyTypeName} value) => d.SetValue({setterArg0}, value);"        );
            }
Ejemplo n.º 8
0
        internal static bool TryGetRegisteredType(FieldOrProperty fieldOrProperty, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ArgumentSyntax?typeArg, [NotNullWhen(true)] out ITypeSymbol?result)
        {
            typeArg = null;
            result  = null;
            if (fieldOrProperty.TryGetAssignedValue(cancellationToken, out var value) &&
                value is InvocationExpressionSyntax invocation)
            {
                if (TryGetRegisterCall(invocation, semanticModel, cancellationToken, out _) &&
                    invocation.TryGetArgumentAtIndex(3, out typeArg))
                {
                    return(typeArg.TryGetTypeofValue(semanticModel, cancellationToken, out result));
                }
            }

            return(false);
        }
        /// <summary>
        /// Get the argument that matches <paramref name="parameter"/>.
        /// </summary>
        /// <param name="initializer">The <see cref="ConstructorInitializerSyntax"/>.</param>
        /// <param name="parameter">The <see cref="IParameterSymbol"/>.</param>
        /// <param name="argument">The <see cref="ArgumentSyntax"/>.</param>
        /// <returns>True if a match was found.</returns>
        public static bool TryFindArgument(this ConstructorInitializerSyntax initializer, IParameterSymbol parameter, [NotNullWhen(true)] out ArgumentSyntax?argument)
        {
            if (initializer is null)
            {
                throw new System.ArgumentNullException(nameof(initializer));
            }

            if (parameter is null)
            {
                throw new System.ArgumentNullException(nameof(parameter));
            }

            argument = null;
            return(initializer.ArgumentList is { } argumentList&&
                   argumentList.TryFind(parameter, out argument));
        }
Ejemplo n.º 10
0
        private static bool TryGetArgs(SyntaxNodeAnalysisContext context, [NotNullWhen(true)] out IMethodSymbol?target, [NotNullWhen(true)] out ArgumentSyntax?propertyArg, [NotNullWhen(true)] out ArgumentSyntax?valueArg)
        {
            if (context.Node is InvocationExpressionSyntax invocation)
            {
                var propertyParameter = QualifiedParameter.Create(KnownSymbols.DependencyProperty);
                var valueParameter    = QualifiedParameter.Create(KnownSymbols.Object);
                return(invocation.TryGetTarget(KnownSymbols.DependencyObject.SetValue, propertyParameter, valueParameter, context.SemanticModel, context.CancellationToken, out target, out propertyArg, out valueArg) ||
                       invocation.TryGetTarget(KnownSymbols.DependencyObject.SetValue, QualifiedParameter.Create(KnownSymbols.DependencyPropertyKey), valueParameter, context.SemanticModel, context.CancellationToken, out target, out propertyArg, out valueArg) ||
                       invocation.TryGetTarget(KnownSymbols.DependencyObject.SetCurrentValue, propertyParameter, valueParameter, context.SemanticModel, context.CancellationToken, out target, out propertyArg, out valueArg));
            }

            target      = null;
            propertyArg = null;
            valueArg    = null;
            return(false);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Get the argument that matches <paramref name="parameter"/>.
        /// </summary>
        /// <param name="argumentList">The <see cref="ArgumentListSyntax"/>.</param>
        /// <param name="parameter">The <see cref="IParameterSymbol"/>.</param>
        /// <param name="argument">The <see cref="ArgumentSyntax"/>.</param>
        /// <returns>True if a match was found.</returns>
        public static bool TryFind(this ArgumentListSyntax argumentList, IParameterSymbol parameter, [NotNullWhen(true)] out ArgumentSyntax?argument)
        {
            if (argumentList is null)
            {
                throw new ArgumentNullException(nameof(argumentList));
            }

            if (parameter is null)
            {
                throw new ArgumentNullException(nameof(parameter));
            }

            switch (argumentList)
            {
            case { Arguments: { Count : 0 } } :
        private static (SyntaxNode source, SyntaxNode destination) GetFluentContractsReplacements(
            IInvocationOperation operation,
            ContractMethodNames contractMethod,
            SemanticModel semanticModel,
            CancellationToken token)
        {
            var invocationExpression = operation.Syntax;

            // Getting the original predicate.
            var predicateArgumentOperation = operation.Arguments[0];
            var predicateArgument          = (ArgumentSyntax)predicateArgumentOperation.Syntax;

            ArgumentSyntax?extraForAllArgument  = null;
            int            messageArgumentIndex = 1;

            // We need to mutate it for the cases like RequiresNotNull and RequiresNotNullOrEmpty

            if (contractMethod.IsNullCheck())
            {
                predicateArgument =
                    Argument(
                        // Changing NotNull(x) to x != null
                        BinaryExpression(
                            SyntaxKind.NotEqualsExpression,
                            predicateArgument.Expression,
                            LiteralExpression(SyntaxKind.NullLiteralExpression)))
                    .NormalizeWhitespace();
            }
            else if (contractMethod.IsNotNullOrEmpty() || contractMethod.IsNotNullOrWhiteSpace())
            {
                var stringMethodName = contractMethod.IsNotNullOrEmpty() ? nameof(string.IsNullOrEmpty) : nameof(string.IsNullOrWhiteSpace);

                // Targeting a full framework can cause an issue for null-ness analysis
                // because string.IsNullOrEmpty and string.IsNullOrWhiteSpace is not annotated with any attributes.
                // It means that the compiler can't recognize that the following code is correct and still emit the warning:
                // if (!string.IsNullOrEmpty(str)) return str.Length;
                predicateArgument =
                    Argument(
                        PrefixUnaryExpression(
                            SyntaxKind.LogicalNotExpression,
                            InvocationExpression(
                                MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    PredefinedType(Token(SyntaxKind.StringKeyword)),
                                    IdentifierName(stringMethodName)))
                            .WithArgumentList(
                                ArgumentList(SingletonSeparatedList(predicateArgument))))
                        ).NormalizeWhitespace();
            }
            else if (contractMethod.IsForAll())
            {
                extraForAllArgument = (ArgumentSyntax)operation.Arguments[1].Syntax;
                messageArgumentIndex++;
            }

            // Detecting the following case:
            // if (predicate is false) {Contract.Assert(false, complicatedMessage);}
            var sourceNode = invocationExpression.Parent;

            if (predicateArgumentOperation.Value is ILiteralOperation lo &&
                lo.ConstantValue.HasValue && lo.ConstantValue.Value.Equals(false))
            {
                // this is Assert(false) case.
                if (operation.Parent?.Parent?.Parent is IConditionalOperation conditional &&
                    conditional.WhenFalse == null &&
                    conditional.WhenTrue.Children.Count() == 1)
                {
                    // The contract is inside the if block with a single statement.
                    sourceNode = conditional.Syntax;

                    var negatedCondition = (ExpressionSyntax?)SyntaxGeneratorExtensions.Negate(conditional.Condition.Syntax, semanticModel, token);
                    if (negatedCondition != null)
                    {
                        predicateArgument = Argument(negatedCondition);
                    }
                }
            }

            var           originalMessageArgument = operation.Arguments[messageArgumentIndex];
            Func <string> nonDefaultArgument      =
                () => contractMethod.IsForAll()
                    ? operation.Arguments[1].Syntax.ToFullString()
                    : predicateArgument.ToFullString();

            // Using an original message if provided.
            // Otherwise using a predicate as the new message.
            var messageArgument =
                originalMessageArgument.IsImplicit == false
                    ? (ArgumentSyntax)originalMessageArgument.Syntax
                    : Argument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(nonDefaultArgument())));

            var arguments =
                new SeparatedSyntaxList <ArgumentSyntax>()
                .Add(predicateArgument)
                .AddIfNotNull(extraForAllArgument);

            // Generating Contract.Check(predicate)?.Requires/Assert(message)

            var targetMethodName = GetTargetMethod(contractMethod);
            var checkMethodName  = GetCheckMethod(contractMethod);
            var contractCall     =
                ExpressionStatement(
                    ConditionalAccessExpression(
                        // Contract.Requires(
                        InvocationExpression(
                            MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                IdentifierName(FluentContractNames.ContractClassName),
                                IdentifierName(checkMethodName)))
                        // (predicate)
                        .WithArgumentList(
                            ArgumentList(arguments)),
                        // ?.IsTrue(message)
                        InvocationExpression(
                            MemberBindingExpression(
                                IdentifierName(targetMethodName)))
                        .WithArgumentList(
                            ArgumentList(
                                SingletonSeparatedList(messageArgument)))
                        )
                    );

            var trivia    = sourceNode.GetLeadingTrivia();
            var finalNode = contractCall.WithLeadingTrivia(trivia);

            return(sourceNode, finalNode);
        }
        public ConstantParsedBindExpression(
            SemanticModelDecorator semanticModel,
            ExpressionStatementSyntax expressionNode,
            List <Tuple <InvocationExpressionSyntax, IMethodSymbol> > invocationSymbols
            ) : base(BindScopeEnum.Constant, invocationSymbols)
        {
            if (semanticModel is null)
            {
                throw new ArgumentNullException(nameof(semanticModel));
            }

            if (expressionNode is null)
            {
                throw new ArgumentNullException(nameof(expressionNode));
            }

            if (invocationSymbols is null)
            {
                throw new ArgumentNullException(nameof(invocationSymbols));
            }

            _semanticModel     = semanticModel;
            _expressionNode    = expressionNode;
            _invocationSymbols = invocationSymbols;

            var constantClause = DetermineArgumentSubClause(
                invocationSymbols,
                typeof(IToOrConstantBinding).GetMethod(nameof(IToOrConstantBinding.WithConstScope), BindingFlags.Public | BindingFlags.Instance) !
                );

            if (constantClause is null)
            {
                throw new DpdtException(
                          DpdtExceptionTypeEnum.InternalError,
                          $"Cannot find constant clause"
                          );
            }

            _constantClause = constantClause;

            _from = invocationSymbols.First(
                s => s.Item2.ContainingType.ToGlobalDisplayString() == typeof(DefaultCluster).ToGlobalDisplayString() && s.Item2.Name == DefaultCluster.BindMethodName
                );
            _fromTypes = _from.Item2.TypeArguments;

            if (_fromTypes.Any(t => t is IDynamicTypeSymbol))
            {
                throw new DpdtException(
                          DpdtExceptionTypeEnum.IncorrectBinding_IncorrectFrom,
                          $"Dynamic cannot be used as bind from type"
                          );
            }

            _constScope = invocationSymbols.First(
                s => s.Item2.ContainingType.ToGlobalDisplayString() == typeof(IToOrConstantBinding).ToGlobalDisplayString() && s.Item2.Name == nameof(IToOrConstantBinding.WithConstScope)
                );

            //euristric if constant is a dynamic actually
            if (_constScope.Item2.TypeArguments[0].TypeKind == TypeKind.TypeParameter)
            {
                throw new DpdtException(
                          DpdtExceptionTypeEnum.IncorrectBinding_IncorrectFrom,
                          $"Dynamic cannot be used as bind from type"
                          );
            }

            _whenArgumentClause = DetermineArgumentSubClause(
                invocationSymbols,
                typeof(IConditionalBinding).GetMethod(nameof(IConditionalBinding.When), BindingFlags.Public | BindingFlags.Instance) !,
                typeof(IConstantConditionalBinding).GetMethod(nameof(IConstantConditionalBinding.When), BindingFlags.Public | BindingFlags.Instance) !
                );
        }
Ejemplo n.º 14
0
 internal static bool TryGetCoerceValueCallback(ObjectCreationExpressionSyntax objectCreation, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ArgumentSyntax?callback)
 {
     return(TryGetCallback(objectCreation, KnownSymbols.CoerceValueCallback, semanticModel, cancellationToken, out callback));
 }
Ejemplo n.º 15
0
        internal static bool TryGetDefaultValue(ObjectCreationExpressionSyntax objectCreation, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ArgumentSyntax?defaultValueArg)
        {
            defaultValueArg = null;
            if (objectCreation?.ArgumentList == null ||
                objectCreation.ArgumentList.Arguments.Count == 0)
            {
                return(false);
            }

            return(TryGetConstructor(objectCreation, semanticModel, cancellationToken, out var constructor) &&
                   constructor.Parameters.TryFirst(out var parameter) &&
                   parameter.Type == KnownSymbols.Object &&
                   objectCreation.ArgumentList.Arguments.TryFirst(out defaultValueArg));
        }
        private static bool TryGetAddHandlerCall(InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, [NotNullWhen(true)] out ArgumentSyntax?eventArgument)
        {
            eventArgument = null;
            if (invocation.TryGetMethodName(out var name) &&
                name != "AddHandler")
            {
                return(false);
            }

            if (invocation.ArgumentList == null ||
                invocation.ArgumentList.Arguments.Count < 2 ||
                invocation.ArgumentList.Arguments.Count > 3)
            {
                return(false);
            }

            return(invocation.TryGetArgumentAtIndex(0, out eventArgument) &&
                   context.SemanticModel.GetTypeInfoSafe(eventArgument.Expression, context.CancellationToken).Type == KnownSymbols.RoutedEvent);
        }
Ejemplo n.º 17
0
        private static bool PreferIsDefined(InvocationExpressionSyntax invocation, IMethodSymbol target, ExpressionSyntax member, ArgumentAndValue <ITypeSymbol> attributeType, ArgumentSyntax?inherits, [NotNullWhen(true)] out Location?location, [NotNullWhen(true)] out string?invocationText)
        {
            switch (invocation.Parent)
            {
            case BinaryExpressionSyntax binary when binary.Right.IsKind(SyntaxKind.NullLiteralExpression):
                if (binary.IsKind(SyntaxKind.EqualsExpression))
                {
                    location       = binary.GetLocation();
                    invocationText = "!" + GetText();
                    return(true);
                }

                if (binary.IsKind(SyntaxKind.NotEqualsExpression))
                {
                    location       = binary.GetLocation();
                    invocationText = GetText();
                    return(true);
                }

                break;

            case IsPatternExpressionSyntax {
                    Pattern: ConstantPatternSyntax constantPattern
            } isPattern
                when constantPattern.Expression.IsKind(SyntaxKind.NullLiteralExpression) :
                    location = isPattern.GetLocation();

                invocationText = "!" + GetText();
                return(true);
            }

            location       = null;
            invocationText = null;
            return(false);

            string GetText()
            {
                var inheritsText = inherits is null ? string.Empty : $", {inherits}";

                return(target.IsExtensionMethod
                    ? $"{member}.IsDefined({attributeType.Argument}{inheritsText})"
                    : $"Attribute.IsDefined({member}, {attributeType.Argument}{inheritsText})");
            }
        }
        private static bool IsValidatedNotNull(string possibleNullReference, BlockSyntax parent, SyntaxNode node,
                                               [NotNullWhen(true)] out SyntaxNode?suppressionCause)
        {
            suppressionCause = default(SyntaxNode);

            StatementSyntax?statement = node?.AncestorsAndSelf().OfType <StatementSyntax>().FirstOrDefault();
            var             siblings  = parent.ChildNodes().ToList();

            // Look in earlier statements to see if the variable was previously checked for null.
            for (int nodeIndex = siblings.FindIndex(x => x == statement); --nodeIndex >= 0;)
            {
                SyntaxNode previous = siblings[nodeIndex];

                suppressionCause = previous;
                if (previous is ExpressionStatementSyntax expressionStatement)
                {
                    if (expressionStatement.Expression is AssignmentExpressionSyntax assignmentExpression)
                    {
                        // Is the offending symbol assigned here?
                        if (InvalidatedBy(assignmentExpression.Left.ToString(), possibleNullReference))
                        {
                            return(IsKnownToBeNotNull(assignmentExpression.Right));
                        }
                    }

                    // Check if this is Assert.NotNull or Assert.IsNotNull for the same symbol
                    if (IsAssert(expressionStatement.Expression, out string member, out ArgumentListSyntax? argumentList))
                    {
                        if (member == NunitFrameworkConstants.NameOfAssertNotNull ||
                            member == NunitFrameworkConstants.NameOfAssertIsNotNull ||
                            member == NunitFrameworkConstants.NameOfAssertThat)
                        {
                            if (member == NunitFrameworkConstants.NameOfAssertThat)
                            {
                                // We must check the 2nd argument for anything but "Is.Null"
                                // E.g.: Is.Not.Null.And.Not.Empty.
                                ArgumentSyntax?secondArgument = argumentList.Arguments.ElementAtOrDefault(1);
                                if (secondArgument?.ToString() == "Is.Null")
                                {
                                    continue;
                                }
                            }

                            ArgumentSyntax firstArgument = argumentList.Arguments.First();
                            if (CoveredBy(firstArgument.Expression.ToString(), possibleNullReference))
                            {
                                return(true);
                            }
                        }
                    }
                }
                else if (previous is LocalDeclarationStatementSyntax localDeclarationStatement)
                {
                    VariableDeclarationSyntax declaration = localDeclarationStatement.Declaration;
                    foreach (var variable in declaration.Variables)
                    {
                        if (variable.Identifier.ToString() == possibleNullReference)
                        {
                            return(IsKnownToBeNotNull(variable.Initializer?.Value));
                        }
                    }
                }
            }

            return(false);
        }
Ejemplo n.º 19
0
 /// <summary>
 /// Get the argument that matches <paramref name="parameter"/>.
 /// </summary>
 /// <param name="initializer">The <see cref="ConstructorInitializerSyntax"/>.</param>
 /// <param name="parameter">The <see cref="IParameterSymbol"/>.</param>
 /// <param name="argument">The <see cref="ArgumentSyntax"/>.</param>
 /// <returns>True if a match was found.</returns>
 public static bool TryFindArgument(this ConstructorInitializerSyntax initializer, IParameterSymbol parameter, [NotNullWhen(true)] out ArgumentSyntax?argument)
 {
     argument = null;
     return(initializer?.ArgumentList is ArgumentListSyntax argumentList &&
            argumentList.TryFind(parameter, out argument));
 }
Ejemplo n.º 20
0
 internal static bool TryGetArgumentAtIndex(this InvocationExpressionSyntax?invocation, int index, [NotNullWhen(true)] out ArgumentSyntax?result)
 {
     result = null;
     return(invocation?.ArgumentList?.Arguments.TryElementAt(index, out result) == true);
 }
Ejemplo n.º 21
0
        private void ProcessCustom(
            ExpressionStatementSyntax expressionNode,
            GenericNameSyntax bindGenericNode,
            ArgumentSyntax?whenArgumentClause
            )
        {
            var genericNodes = expressionNode
                               .DescendantNodes()
                               .OfType <GenericNameSyntax>()
                               .ToList();

            var toGenericNode = genericNodes[1];
            var toMethodName  = toGenericNode.Identifier.Text;

            if (toMethodName.NotIn(nameof(IToOrConstantBinding.To), nameof(IToOrConstantBinding.ToFactory)))
            {
                throw new DpdtException(DpdtExceptionTypeEnum.InternalError, "Cannot find To clause for custom binding");
            }

            var factoryPayloadSemantic = GetFactoryPayloadIfExists(
                toGenericNode
                );

            var bindFromTypeSemantics = GetBindFromTypes(
                bindGenericNode
                );

            var bindToSyntax       = toGenericNode.TypeArgumentList.Arguments.First();
            var bindToTypeSemantic = _semanticModel.GetTypeInfo(bindToSyntax).Type;

            if (bindToTypeSemantic == null)
            {
                throw new DpdtException(
                          DpdtExceptionTypeEnum.InternalError,
                          $"Unknown problem to access {nameof(bindToTypeSemantic)}"
                          );
            }

            CheckForFromAndToTypes(
                bindFromTypeSemantics,
                bindToTypeSemantic,
                !(factoryPayloadSemantic is null)
                );

            var fullBindToTypeName = _typeInfoProvider.GetTypeByMetadataName(bindToTypeSemantic.ToDisplayString());

            if (fullBindToTypeName == null)
            {
                throw new DpdtException(
                          DpdtExceptionTypeEnum.InternalError,
                          $"Unknown problem to access type for {bindToTypeSemantic.ToDisplayString()}"
                          );
            }

            var caExtractor = new ConstructorArgumentExtractor(
                _typeInfoProvider,
                _semanticModel
                );

            caExtractor.Visit(expressionNode);

            var constructorArguments = GetConstructorArguments(
                caExtractor,
                fullBindToTypeName
                );

            var bindingContainer = new BindingContainerWithInstance(
                bindFromTypeSemantics,
                bindToTypeSemantic,
                constructorArguments,
                BindScopeEnum.Custom,
                whenArgumentClause,
                factoryPayloadSemantic
                );

            _bindingContainers.Add(bindingContainer);
        }
Ejemplo n.º 22
0
 internal static bool TrySingleArgument(this InvocationExpressionSyntax?invocation, [NotNullWhen(true)] out ArgumentSyntax?result)
 {
     result = null;
     return(invocation?.ArgumentList?.Arguments.TrySingle(out result) == true);
 }
Ejemplo n.º 23
0
 internal ArgumentAndValue(ArgumentSyntax?argument, T value)
 {
     this.Argument = argument;
     this.Value    = value;
 }
Ejemplo n.º 24
0
        private static bool TryGetArgs(InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, [NotNullWhen(true)] out IMethodSymbol?target, [NotNullWhen(true)] out ExpressionSyntax?member, out ArgumentAndValue <ITypeSymbol> attributeType, out ArgumentSyntax?inheritsArg)
        {
            if ((invocation.TryGetTarget(KnownSymbol.Attribute.IsDefined, context.SemanticModel, context.CancellationToken, out target) ||
                 invocation.TryGetTarget(KnownSymbol.CustomAttributeExtensions.IsDefined, context.SemanticModel, context.CancellationToken, out target)) &&
                target.TryFindParameter("attributeType", out var attributeTypeParameter) &&
                invocation.TryFindArgument(attributeTypeParameter, out var attributeTypeArg) &&
                attributeTypeArg.Expression is TypeOfExpressionSyntax typeOf &&
                context.SemanticModel.TryGetType(typeOf.Type, context.CancellationToken, out var typeSymbol))
            {
                attributeType = new ArgumentAndValue <ITypeSymbol>(attributeTypeArg, typeSymbol);
                if (!target.TryFindParameter("inherit", out var inheritParameter) ||
                    !invocation.TryFindArgument(inheritParameter, out inheritsArg))
                {
                    inheritsArg = null;
                }

                if (target.IsExtensionMethod &&
                    invocation.Expression is MemberAccessExpressionSyntax memberAccess)
                {
                    member = memberAccess.Expression;
                    return(true);
                }

                if (target.TryFindParameter("element", out var elementParameter) &&
                    invocation.TryFindArgument(elementParameter, out var elementArg))
                {
                    member = elementArg.Expression;
                    return(true);
                }
            }

            member        = null;
            attributeType = default;
            inheritsArg   = null;
            return(false);
        }
Ejemplo n.º 25
0
 internal static bool TryGetRegisteredName(ObjectCreationExpressionSyntax objectCreation, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ArgumentSyntax?nameArg, out string registeredName)
 {
     nameArg        = null;
     registeredName = null;
     return(TryGetConstructor(objectCreation, semanticModel, cancellationToken, out _) &&
            objectCreation.TryFirstAncestor(out InvocationExpressionSyntax? invocation) &&
            DependencyProperty.TryGetRegisteredName(invocation, semanticModel, cancellationToken, out nameArg, out registeredName));
 }
Ejemplo n.º 26
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            Diagnostic?diagnostic = context.Diagnostics.First();

            SyntaxNode?root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var syntaxNode = (ExpressionSyntax)root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true);

            CSharpUtils.ContainingFunctionData container = CSharpUtils.GetContainingFunction(syntaxNode);
            if (container.BlockOrExpression is null)
            {
                return;
            }

            SemanticModel?semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            ISymbol?enclosingSymbol = semanticModel.GetEnclosingSymbol(diagnostic.Location.SourceSpan.Start, context.CancellationToken);

            if (enclosingSymbol is null)
            {
                return;
            }

            bool convertToAsync = !container.IsAsync && Utils.HasAsyncCompatibleReturnType(enclosingSymbol as IMethodSymbol);

            if (convertToAsync)
            {
                // We don't support this yet, and we don't want to take the sync method path in this case.
                // The user will have to fix this themselves.
                return;
            }

            Regex lookupKey = (container.IsAsync || convertToAsync)
                ? CommonInterest.FileNamePatternForMethodsThatSwitchToMainThread
                : CommonInterest.FileNamePatternForMethodsThatAssertMainThread;

            string[] options = diagnostic.Properties[lookupKey.ToString()].Split('\n');
            if (options.Length > 0)
            {
                // For any symbol lookups, we want to consider the position of the very first statement in the block.
                int positionForLookup = container.BlockOrExpression.GetLocation().SourceSpan.Start + 1;

                Lazy <ISymbol> cancellationTokenSymbol = new Lazy <ISymbol>(() => Utils.FindCancellationToken(semanticModel, positionForLookup, context.CancellationToken).FirstOrDefault());
                foreach (var option in options)
                {
                    // We're looking for methods that either require no parameters,
                    // or (if we have one to give) that have just one parameter that is a CancellationToken.
                    IMethodSymbol?proposedMethod = Utils.FindMethodGroup(semanticModel, option)
                                                   .FirstOrDefault(m => !m.Parameters.Any(p => !p.HasExplicitDefaultValue) ||
                                                                   (cancellationTokenSymbol.Value is object && m.Parameters.Length == 1 && Utils.IsCancellationTokenParameter(m.Parameters[0])));
                    if (proposedMethod is null)
                    {
                        // We can't find it, so don't offer to use it.
                        continue;
                    }

                    if (proposedMethod.IsStatic)
                    {
                        OfferFix(option);
                    }
                    else
                    {
                        foreach (Tuple <bool, ISymbol>?candidate in Utils.FindInstanceOf(proposedMethod.ContainingType, semanticModel, positionForLookup, context.CancellationToken))
                        {
                            if (candidate.Item1)
                            {
                                OfferFix($"{candidate.Item2.Name}.{proposedMethod.Name}");
                            }
                            else
                            {
                                OfferFix($"{candidate.Item2.ContainingNamespace}.{candidate.Item2.ContainingType.Name}.{candidate.Item2.Name}.{proposedMethod.Name}");
                            }
                        }
                    }

                    void OfferFix(string fullyQualifiedMethod)
                    {
                        context.RegisterCodeFix(CodeAction.Create($"Add call to {fullyQualifiedMethod}", ct => Fix(fullyQualifiedMethod, proposedMethod, cancellationTokenSymbol), fullyQualifiedMethod), context.Diagnostics);
                    }
                }
            }

            Task <Document> Fix(string fullyQualifiedMethod, IMethodSymbol methodSymbol, Lazy <ISymbol> cancellationTokenSymbol)
            {
                int typeAndMethodDelimiterIndex                       = fullyQualifiedMethod.LastIndexOf('.');
                IdentifierNameSyntax       methodName                 = SyntaxFactory.IdentifierName(fullyQualifiedMethod.Substring(typeAndMethodDelimiterIndex + 1));
                ExpressionSyntax           invokedMethod              = CSharpUtils.MemberAccess(fullyQualifiedMethod.Substring(0, typeAndMethodDelimiterIndex).Split('.'), methodName);
                InvocationExpressionSyntax?invocationExpression       = SyntaxFactory.InvocationExpression(invokedMethod);
                IParameterSymbol?          cancellationTokenParameter = methodSymbol.Parameters.FirstOrDefault(Utils.IsCancellationTokenParameter);

                if (cancellationTokenParameter is object && cancellationTokenSymbol.Value is object)
                {
                    ArgumentSyntax?arg = SyntaxFactory.Argument(SyntaxFactory.IdentifierName(cancellationTokenSymbol.Value.Name));
                    if (methodSymbol.Parameters.IndexOf(cancellationTokenParameter) > 0)
                    {
                        arg = arg.WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName(cancellationTokenParameter.Name)));
                    }

                    invocationExpression = invocationExpression.AddArgumentListArguments(arg);
                }

                ExpressionSyntax?         awaitExpression = container.IsAsync ? SyntaxFactory.AwaitExpression(invocationExpression) : null;
                ExpressionStatementSyntax?addedStatement  = SyntaxFactory.ExpressionStatement(awaitExpression ?? invocationExpression)
                                                            .WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation);
                var initialBlockSyntax = container.BlockOrExpression as BlockSyntax;

                if (initialBlockSyntax is null)
                {
                    SyntaxToken openBrace  = SyntaxFactory.Token(SyntaxFactory.TriviaList(), SyntaxKind.OpenBraceToken, SyntaxFactory.TriviaList(SyntaxFactory.EndOfLine("\r\n")));
                    SyntaxToken closeBrace = SyntaxFactory.Token(SyntaxKind.CloseBraceToken);
                    SyntaxList <StatementSyntax> statementList = SyntaxFactory.List <StatementSyntax>(new[] { SyntaxFactory.ReturnStatement((ExpressionSyntax)container.BlockOrExpression) });
                    initialBlockSyntax = SyntaxFactory.Block(openBrace, statementList, closeBrace)
                                         .WithAdditionalAnnotations(Formatter.Annotation);
                }

                BlockSyntax?newBlock = initialBlockSyntax.WithStatements(initialBlockSyntax.Statements.Insert(0, addedStatement));

                return(Task.FromResult(context.Document.WithSyntaxRoot(root.ReplaceNode(container.BlockOrExpression.Parent, container.BodyReplacement(newBlock)))));
            }
        }
Ejemplo n.º 27
0
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            foreach (Diagnostic?diagnostic in context.Diagnostics)
            {
                SyntaxNode?root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

                ExpressionSyntax?syntaxNode = root.FindNode(diagnostic.Location.SourceSpan, getInnermostNodeForTie: true) as ExpressionSyntax;
                if (syntaxNode is null)
                {
                    continue;
                }

                CSharpUtils.ContainingFunctionData container = CSharpUtils.GetContainingFunction(syntaxNode);
                if (container.BlockOrExpression is null)
                {
                    return;
                }

                if (!container.IsAsync)
                {
                    if (!(container.Function is MethodDeclarationSyntax || container.Function is AnonymousFunctionExpressionSyntax))
                    {
                        // We don't support converting whatever this is into an async method.
                        return;
                    }
                }

                SemanticModel?semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

                ISymbol?enclosingSymbol = semanticModel.GetEnclosingSymbol(diagnostic.Location.SourceSpan.Start, context.CancellationToken);
                if (enclosingSymbol is null)
                {
                    return;
                }

                var hasReturnValue = ((enclosingSymbol as IMethodSymbol)?.ReturnType as INamedTypeSymbol)?.IsGenericType ?? false;
                ImmutableArray <CommonInterest.QualifiedMember> options = await CommonFixes.ReadMethodsAsync(context, CommonInterest.FileNamePatternForMethodsThatSwitchToMainThread, context.CancellationToken);

                int     positionForLookup       = diagnostic.Location.SourceSpan.Start;
                ISymbol cancellationTokenSymbol = Utils.FindCancellationToken(semanticModel, positionForLookup, context.CancellationToken).FirstOrDefault();
                foreach (CommonInterest.QualifiedMember option in options)
                {
                    // We're looking for methods that either require no parameters,
                    // or (if we have one to give) that have just one parameter that is a CancellationToken.
                    IMethodSymbol?proposedMethod = Utils.FindMethodGroup(semanticModel, option)
                                                   .FirstOrDefault(m => !m.Parameters.Any(p => !p.HasExplicitDefaultValue) ||
                                                                   (cancellationTokenSymbol is object && m.Parameters.Length == 1 && Utils.IsCancellationTokenParameter(m.Parameters[0])));
                    if (proposedMethod is null)
                    {
                        // We can't find it, so don't offer to use it.
                        continue;
                    }

                    if (proposedMethod.IsStatic)
                    {
                        OfferFix(option.ToString());
                    }
                    else
                    {
                        foreach (Tuple <bool, ISymbol>?candidate in Utils.FindInstanceOf(proposedMethod.ContainingType, semanticModel, positionForLookup, context.CancellationToken))
                        {
                            if (candidate.Item1)
                            {
                                OfferFix($"{candidate.Item2.Name}.{proposedMethod.Name}");
                            }
                            else
                            {
                                OfferFix($"{candidate.Item2.ContainingNamespace}.{candidate.Item2.ContainingType.Name}.{candidate.Item2.Name}.{proposedMethod.Name}");
                            }
                        }
                    }

                    void OfferFix(string fullyQualifiedMethod)
                    {
                        context.RegisterCodeFix(CodeAction.Create($"Use 'await {fullyQualifiedMethod}'", ct => Fix(fullyQualifiedMethod, proposedMethod, hasReturnValue, ct), fullyQualifiedMethod), context.Diagnostics);
                    }
                }

                async Task <Solution> Fix(string fullyQualifiedMethod, IMethodSymbol methodSymbol, bool hasReturnValue, CancellationToken cancellationToken)
                {
                    StatementSyntax?assertionStatementToRemove = syntaxNode !.FirstAncestorOrSelf <StatementSyntax>();

                    int typeAndMethodDelimiterIndex    = fullyQualifiedMethod.LastIndexOf('.');
                    IdentifierNameSyntax methodName    = SyntaxFactory.IdentifierName(fullyQualifiedMethod.Substring(typeAndMethodDelimiterIndex + 1));
                    ExpressionSyntax     invokedMethod = CSharpUtils.MemberAccess(fullyQualifiedMethod.Substring(0, typeAndMethodDelimiterIndex).Split('.'), methodName)
                                                         .WithAdditionalAnnotations(Simplifier.Annotation);
                    InvocationExpressionSyntax?invocationExpression       = SyntaxFactory.InvocationExpression(invokedMethod);
                    IParameterSymbol?          cancellationTokenParameter = methodSymbol.Parameters.FirstOrDefault(Utils.IsCancellationTokenParameter);

                    if (cancellationTokenParameter is object && cancellationTokenSymbol is object)
                    {
                        ArgumentSyntax?arg = SyntaxFactory.Argument(SyntaxFactory.IdentifierName(cancellationTokenSymbol.Name));
                        if (methodSymbol.Parameters.IndexOf(cancellationTokenParameter) > 0)
                        {
                            arg = arg.WithNameColon(SyntaxFactory.NameColon(SyntaxFactory.IdentifierName(cancellationTokenParameter.Name)));
                        }

                        invocationExpression = invocationExpression.AddArgumentListArguments(arg);
                    }

                    ExpressionSyntax          awaitExpression = SyntaxFactory.AwaitExpression(invocationExpression);
                    ExpressionStatementSyntax?addedStatement  = SyntaxFactory.ExpressionStatement(awaitExpression)
                                                                .WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation);

                    var methodAnnotation          = new SyntaxAnnotation();
                    CSharpSyntaxNode methodSyntax = container.Function.ReplaceNode(assertionStatementToRemove, addedStatement)
                                                    .WithAdditionalAnnotations(methodAnnotation);
                    Document   newDocument   = context.Document.WithSyntaxRoot(root.ReplaceNode(container.Function, methodSyntax));
                    SyntaxNode?newSyntaxRoot = await newDocument.GetSyntaxRootAsync(cancellationToken);

                    methodSyntax = (CSharpSyntaxNode)newSyntaxRoot.GetAnnotatedNodes(methodAnnotation).Single();
                    if (!container.IsAsync)
                    {
                        switch (methodSyntax)
                        {
                        case AnonymousFunctionExpressionSyntax anonFunc:
                            semanticModel = await newDocument.GetSemanticModelAsync(cancellationToken);

                            methodSyntax = FixUtils.MakeMethodAsync(anonFunc, hasReturnValue, semanticModel, cancellationToken);
                            newDocument  = newDocument.WithSyntaxRoot(newSyntaxRoot.ReplaceNode(anonFunc, methodSyntax));
                            break;

                        case MethodDeclarationSyntax methodDecl:
                            (newDocument, methodSyntax) = await FixUtils.MakeMethodAsync(methodDecl, newDocument, cancellationToken);

                            break;
                        }
                    }

                    return(newDocument.Project.Solution);
                }
            }
        }
Ejemplo n.º 28
0
        internal static bool TryGetRegisteredName(BackingFieldOrProperty backing, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ArgumentSyntax?nameArg, [NotNullWhen(true)] out string?result)
        {
            nameArg = null;
            result  = null;
            if (TryGetRegisterInvocationRecursive(backing, semanticModel, cancellationToken, out var invocation, out var method))
            {
                return(method.TryFindParameter("name", out var parameter) &&
                       invocation.TryFindArgument(parameter, out nameArg) &&
                       nameArg.TryGetStringValue(semanticModel, cancellationToken, out result));
            }

            if (TryGetDependencyAddOwnerSourceField(backing, semanticModel, cancellationToken, out var source) &&
                !source.Symbol.Equals(backing.Symbol))
            {
                return(TryGetRegisteredName(source, semanticModel, cancellationToken, out nameArg, out result));
            }

            if (backing.Symbol.Locations.All(x => !x.IsInSource) &&
                TryGetPropertyByName(backing, out var property))
            {
                result = property.Name;
                return(true);
            }

            return(false);
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Get the argument that matches <paramref name="parameter"/>.
        /// </summary>
        /// <param name="objectCreation">The <see cref="ObjectCreationExpressionSyntax"/>.</param>
        /// <param name="parameter">The <see cref="IParameterSymbol"/>.</param>
        /// <param name="argument">The <see cref="ArgumentSyntax"/>.</param>
        /// <returns>True if a match was found.</returns>
        public static bool TryFindArgument(this ObjectCreationExpressionSyntax objectCreation, IParameterSymbol parameter, [NotNullWhen(true)] out ArgumentSyntax?argument)
        {
            if (objectCreation is null)
            {
                throw new System.ArgumentNullException(nameof(objectCreation));
            }

            if (parameter is null)
            {
                throw new System.ArgumentNullException(nameof(parameter));
            }

            argument = null;
            return(objectCreation.ArgumentList is { } argumentList&&
                   argumentList.TryFind(parameter, out argument));
        }
Ejemplo n.º 30
0
        internal static bool TryGetRegisteredName(FieldOrProperty fieldOrProperty, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ArgumentSyntax?nameArg, [NotNullWhen(true)] out string?result)
        {
            nameArg = null;
            result  = null;
            if (fieldOrProperty.TryGetAssignedValue(cancellationToken, out var value) &&
                value is InvocationExpressionSyntax invocation)
            {
                if (TryGetRegisterCall(invocation, semanticModel, cancellationToken, out _) &&
                    invocation.TryGetArgumentAtIndex(0, out nameArg))
                {
                    return(nameArg.TryGetStringValue(semanticModel, cancellationToken, out result));
                }
            }

            return(false);
        }