<commit_before>﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{
    internal partial class ExplicitInterfaceTypeCompletionProvider : AbstractSymbolCompletionProvider
    {
        internal override bool IsInsertionTrigger(SourceText text, int insertedCharacterPosition, OptionSet options)
            => CompletionUtilities.IsTriggerAfterSpaceOrStartOfWordCharacter(text, insertedCharacterPosition, options);

        protected override (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context)
            => CompletionUtilities.GetDisplayAndInsertionText(symbol, context);

        protected override async Task<SyntaxContext> CreateContext(
            Document document, int position, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            return CSharpSyntaxContext.CreateContext(
                document.Project.Solution.Workspace, semanticModel, position, cancellationToken);
        }

        public override async Task ProvideCompletionsAsync(CompletionContext context)
        {
            var completionCount = context.Items.Count;
            await base.ProvideCompletionsAsync(context).ConfigureAwait(false);

            if (completionCount < context.Items.Count)
            {
                // If we added any items, then add a suggestion mode item as this is a location 
                // where a member name could be written, and we should not interfere with that.
                context.SuggestionModeItem = CreateSuggestionModeItem(
                    CSharpFeaturesResources.member_name,
                    CSharpFeaturesResources.Autoselect_disabled_due_to_member_declaration);
            }
        }

        protected override Task<ImmutableArray<ISymbol>> GetSymbolsWorker(
            SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken)
        {
            var targetToken = context.TargetToken;

            // Don't want to offer this after "async" (even though the compiler may parse that as a type).
            if (SyntaxFacts.GetContextualKeywordKind(targetToken.ValueText) == SyntaxKind.AsyncKeyword)
            {
                return SpecializedTasks.EmptyImmutableArray<ISymbol>();
            }

            var typeNode = targetToken.Parent as TypeSyntax;

            while (typeNode != null)
            {
                if (typeNode.Parent is TypeSyntax parentType && parentType.Span.End < position)
                {
                    typeNode = parentType;
                }
                else
                {
                    break;
                }
            }

            if (typeNode == null)
            {
                return SpecializedTasks.EmptyImmutableArray<ISymbol>();
            }

            // We weren't after something that looked like a type.
            var tokenBeforeType = typeNode.GetFirstToken().GetPreviousToken();

            if (!IsPreviousTokenValid(tokenBeforeType))
            {
                return SpecializedTasks.EmptyImmutableArray<ISymbol>();
            }

            // Looks syntactically good.  See what interfaces our containing class/struct has
            var typeDeclaration = typeNode.GetAncestor<TypeDeclarationSyntax>();
            Debug.Assert(IsClassOrStruct(typeDeclaration));

            var semanticModel = context.SemanticModel;
            var namedType = semanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken);

            var interfaceSet = new HashSet<INamedTypeSymbol>();
            foreach (var directInterface in namedType.Interfaces)
            {
                interfaceSet.Add(directInterface);
                interfaceSet.AddRange(directInterface.AllInterfaces);
            }

            return Task.FromResult(interfaceSet.ToImmutableArray<ISymbol>());
        }

        protected override CompletionItemRules GetCompletionItemRules(IReadOnlyList<ISymbol> symbols)
            => s_rules;

        private bool IsPreviousTokenValid(SyntaxToken tokenBeforeType)
        {
            if (tokenBeforeType.Kind() == SyntaxKind.OpenBraceToken)
            {
                // Show us after the open brace for a class/struct
                return IsClassOrStruct(tokenBeforeType.Parent);
            }

            if (tokenBeforeType.Kind() == SyntaxKind.CloseBraceToken ||
                tokenBeforeType.Kind() == SyntaxKind.SemicolonToken)
            {
                // Check that we're after a class/struct member.
                var memberDeclaration = tokenBeforeType.GetAncestor<MemberDeclarationSyntax>();
                return memberDeclaration?.GetLastToken() == tokenBeforeType &&
                       IsClassOrStruct(memberDeclaration.Parent);
            }

            return false;
        }

        private static bool IsClassOrStruct(SyntaxNode node)
            => node.Kind() == SyntaxKind.ClassDeclaration || node.Kind() == SyntaxKind.StructDeclaration;

        private static CompletionItemRules s_rules = CompletionItemRules.Default.WithSelectionBehavior(CompletionItemSelectionBehavior.SoftSelection);
    }
}<commit_msg>Remove unnecessary code.<commit_after>﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Completion.Providers;
using Microsoft.CodeAnalysis.CSharp.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.Completion.Providers
{
    internal partial class ExplicitInterfaceTypeCompletionProvider : AbstractSymbolCompletionProvider
    {
        internal override bool IsInsertionTrigger(SourceText text, int insertedCharacterPosition, OptionSet options)
            => CompletionUtilities.IsTriggerAfterSpaceOrStartOfWordCharacter(text, insertedCharacterPosition, options);

        protected override (string displayText, string insertionText) GetDisplayAndInsertionText(ISymbol symbol, SyntaxContext context)
            => CompletionUtilities.GetDisplayAndInsertionText(symbol, context);

        protected override async Task<SyntaxContext> CreateContext(
            Document document, int position, CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
            return CSharpSyntaxContext.CreateContext(
                document.Project.Solution.Workspace, semanticModel, position, cancellationToken);
        }

        public override async Task ProvideCompletionsAsync(CompletionContext context)
        {
            var completionCount = context.Items.Count;
            await base.ProvideCompletionsAsync(context).ConfigureAwait(false);

            if (completionCount < context.Items.Count)
            {
                // If we added any items, then add a suggestion mode item as this is a location 
                // where a member name could be written, and we should not interfere with that.
                context.SuggestionModeItem = CreateSuggestionModeItem(
                    CSharpFeaturesResources.member_name,
                    CSharpFeaturesResources.Autoselect_disabled_due_to_member_declaration);
            }
        }

        protected override Task<ImmutableArray<ISymbol>> GetSymbolsWorker(
            SyntaxContext context, int position, OptionSet options, CancellationToken cancellationToken)
        {
            var targetToken = context.TargetToken;

            // Don't want to offer this after "async" (even though the compiler may parse that as a type).
            if (SyntaxFacts.GetContextualKeywordKind(targetToken.ValueText) == SyntaxKind.AsyncKeyword)
            {
                return SpecializedTasks.EmptyImmutableArray<ISymbol>();
            }

            var typeNode = targetToken.Parent as TypeSyntax;

            while (typeNode != null)
            {
                if (typeNode.Parent is TypeSyntax parentType && parentType.Span.End < position)
                {
                    typeNode = parentType;
                }
                else
                {
                    break;
                }
            }

            if (typeNode == null)
            {
                return SpecializedTasks.EmptyImmutableArray<ISymbol>();
            }

            // We weren't after something that looked like a type.
            var tokenBeforeType = typeNode.GetFirstToken().GetPreviousToken();

            if (!IsPreviousTokenValid(tokenBeforeType))
            {
                return SpecializedTasks.EmptyImmutableArray<ISymbol>();
            }

            // Looks syntactically good.  See what interfaces our containing class/struct has
            var typeDeclaration = typeNode.GetAncestor<TypeDeclarationSyntax>();
            Debug.Assert(IsClassOrStruct(typeDeclaration));

            var semanticModel = context.SemanticModel;
            var namedType = semanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken);

            var interfaceSet = new HashSet<INamedTypeSymbol>();
            foreach (var directInterface in namedType.Interfaces)
            {
                interfaceSet.Add(directInterface);
                interfaceSet.AddRange(directInterface.AllInterfaces);
            }

            return Task.FromResult(interfaceSet.ToImmutableArray<ISymbol>());
        }

        protected override CompletionItemRules GetCompletionItemRules(IReadOnlyList<ISymbol> symbols)
            => s_rules;

        private bool IsPreviousTokenValid(SyntaxToken tokenBeforeType)
        {
            if (tokenBeforeType.Kind() == SyntaxKind.OpenBraceToken)
            {
                // Show us after the open brace for a class/struct
                return IsClassOrStruct(tokenBeforeType.Parent);
            }

            if (tokenBeforeType.Kind() == SyntaxKind.CloseBraceToken ||
                tokenBeforeType.Kind() == SyntaxKind.SemicolonToken)
            {
                // Check that we're after a class/struct member.
                var memberDeclaration = tokenBeforeType.GetAncestor<MemberDeclarationSyntax>();
                return memberDeclaration?.GetLastToken() == tokenBeforeType &&
                       IsClassOrStruct(memberDeclaration.Parent);
            }

            return false;
        }

        private static bool IsClassOrStruct(SyntaxNode node)
            => node.Kind() == SyntaxKind.ClassDeclaration || node.Kind() == SyntaxKind.StructDeclaration;
    }
}
{'fraction_non_alphanumeric': 0.06915300314331832, 'fraction_numerical': 0.00033981819726446353, 'mean_word_length': 2.4890337877889745, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6966645', 'n_tokens_mistral': 2749, 'n_tokens_neox': 2644, 'n_words': 639}