public override Task ProvideArgumentAsync(ArgumentContext context)
        {
            if (context.PreviousValue is not null)
            {
                // This argument provider does not attempt to replace arguments already in code.
                return(Task.CompletedTask);
            }

            var symbols = context.SemanticModel.LookupSymbols(
                context.Position,
                name: context.Parameter.Name
                );

            foreach (var symbol in symbols)
            {
                // Currently we check for an exact type match before using a variable from context. As we hone the
                // default argument provider heuristics, we may alter the definition of "in scope" as well as the type
                // and name check(s) that occur.
                if (
                    SymbolEqualityComparer.Default.Equals(
                        context.Parameter.Type,
                        symbol.GetSymbolType()
                        )
                    )
                {
                    context.DefaultValue = context.Parameter.Name;
                    return(Task.CompletedTask);
                }
            }

            return(Task.CompletedTask);
        }
        public override async Task ProvideArgumentAsync(ArgumentContext context)
        {
            if (context.PreviousValue is not null)
            {
                // This argument provider does not attempt to replace arguments already in code.
                return;
            }

            var requireExactType = context.Parameter.Type.IsSpecialType() ||
                                   context.Parameter.RefKind != RefKind.None;
            var symbols = context.SemanticModel.LookupSymbols(context.Position);

            // First try to find a local variable
            ISymbol?         bestSymbol     = null;
            string?          bestSymbolName = null;
            CommonConversion bestConversion = default;

            foreach (var symbol in symbols)
            {
                ISymbol candidate;
                if (symbol.IsKind(SymbolKind.Parameter, out IParameterSymbol? parameter))
                {
                    candidate = parameter;
                }
                else if (symbol.IsKind(SymbolKind.Local, out ILocalSymbol? local))
                {
                    candidate = local;
                }
                else
                {
                    continue;
                }

                CheckCandidate(candidate);
            }

            if (bestSymbol is not null)
            {
                context.DefaultValue = bestSymbolName;
                return;
            }

            // Next try fields and properties of the current type
            foreach (var symbol in symbols)
            {
                ISymbol candidate;
                if (symbol.IsKind(SymbolKind.Field, out IFieldSymbol? field))
                {
                    candidate = field;
                }
                else if (symbol.IsKind(SymbolKind.Property, out IPropertySymbol? property))
                {
                    candidate = property;
                }
                else
                {
                    continue;
                }

                // Require a name match for primitive types
                if (candidate.GetSymbolType().IsSpecialType() &&
                    !string.Equals(candidate.Name, context.Parameter.Name, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                CheckCandidate(candidate);
            }

            if (bestSymbol is not null)
            {
                context.DefaultValue = bestSymbolName;
                return;
            }

            // Finally, if the invocation occurs in an instance context, check the current type ('this' or 'Me')
            var tree        = context.SemanticModel.SyntaxTree;
            var targetToken = await tree.GetTouchingTokenAsync(context.Position, context.CancellationToken).ConfigureAwait(false);

            if (IsInstanceContext(tree, targetToken, context.SemanticModel, context.CancellationToken))
            {
                var enclosingSymbol = context.SemanticModel.GetEnclosingSymbol(targetToken.SpanStart, context.CancellationToken);
                while (enclosingSymbol is IMethodSymbol {
                    MethodKind: MethodKind.LocalFunction or MethodKind.AnonymousFunction
                } method)
                {
                    // It is allowed to reference the instance (`this`) within a local function or anonymous function,
                    // as long as the containing method allows it
                    enclosingSymbol = enclosingSymbol.ContainingSymbol;
                }

                if (enclosingSymbol is IMethodSymbol {
                    ContainingType: { } containingType
                })