private async Task <NameDeclarationInfo> GetResultsAsync(string markup)
        {
            var(document, position) = ApplyChangesToFixture(markup);
            var result = await NameDeclarationInfo.GetDeclarationInfo(document, position, CancellationToken.None);

            return(result);
        }
        public override async Task ProvideCompletionsAsync(CompletionContext completionContext)
        {
            try
            {
                var position          = completionContext.Position;
                var document          = completionContext.Document;
                var cancellationToken = completionContext.CancellationToken;

                if (!completionContext.CompletionOptions.ShowNameSuggestions)
                {
                    return;
                }

                var context = (CSharpSyntaxContext)await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false);

                if (context.IsInNonUserCode)
                {
                    return;
                }

                // Do not show name suggestions for unbound "async" identifier.
                // Most likely user is writing an async method, so name suggestion will just interfere him
                if (context.TargetToken.IsKindOrHasMatchingText(SyntaxKind.AsyncKeyword) &&
                    context.SemanticModel.GetSymbolInfo(context.TargetToken).GetAnySymbol() is null)
                {
                    return;
                }

                var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false);

                using var _ = ArrayBuilder <(string name, SymbolKind kind)> .GetInstance(out var result);

                // Suggest names from existing overloads.
                if (nameInfo.PossibleSymbolKinds.Any(static k => k.SymbolKind == SymbolKind.Parameter))
예제 #3
0
        private async Task <IEnumerable <(string, SymbolKind)> > GetRecommendedNamesAsync(
            IEnumerable <IEnumerable <string> > baseNames,
            NameDeclarationInfo declarationInfo,
            CSharpSyntaxContext context,
            Document document,
            CancellationToken cancellationToken)
        {
            var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var namingStyleOptions = options.GetOption(SimplificationOptions.NamingPreferences);
            var rules  = namingStyleOptions.CreateRules().NamingRules.Concat(s_BuiltInRules);
            var result = new Dictionary <string, SymbolKind>();

            foreach (var symbolKind in declarationInfo.PossibleSymbolKinds)
            {
                var kind      = new SymbolKindOrTypeKind(symbolKind);
                var modifiers = declarationInfo.Modifiers;
                foreach (var rule in rules)
                {
                    if (rule.SymbolSpecification.AppliesTo(kind, declarationInfo.Modifiers, declarationInfo.DeclaredAccessibility))
                    {
                        foreach (var baseName in baseNames)
                        {
                            var name = rule.NamingStyle.CreateName(baseName);
                            if (name.Length > 1 && !result.ContainsKey(name)) // Don't add multiple items for the same name
                            {
                                result.Add(name, symbolKind);
                            }
                        }
                    }
                }
            }

            return(result.Select(kvp => (kvp.Key, kvp.Value)));
        }
예제 #4
0
 private static bool IsPossibleVariableOrLocalMethodDeclaration(
     SyntaxToken token, SemanticModel semanticModel, int position,
     CancellationToken cancellationToken, out NameDeclarationInfo result)
 {
     result = IsLastTokenOfType <ExpressionStatementSyntax>(
         token, semanticModel,
         e => e.Expression,
         _ => default(SyntaxTokenList),
         _ => ImmutableArray.Create(SymbolKind.Local),
         cancellationToken);
     return(result.Type != null);
 }
        private ImmutableArray <ImmutableArray <string> > GetBaseNames(
            SemanticModel semanticModel,
            NameDeclarationInfo nameInfo
            )
        {
            if (nameInfo.Alias != null)
            {
                return(NameGenerator.GetBaseNames(nameInfo.Alias));
            }

            if (!IsValidType(nameInfo.Type))
            {
                return(default);
예제 #6
0
        public override async Task ProvideCompletionsAsync(CompletionContext completionContext)
        {
            try
            {
                var position          = completionContext.Position;
                var document          = completionContext.Document;
                var cancellationToken = completionContext.CancellationToken;
                var semanticModel     = await document.GetSemanticModelForSpanAsync(new Text.TextSpan(position, 0), cancellationToken).ConfigureAwait(false);

                if (!completionContext.Options.GetOption(CompletionOptions.ShowNameSuggestions, LanguageNames.CSharp))
                {
                    return;
                }

                var context = CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken);
                if (context.IsInNonUserCode)
                {
                    return;
                }

                var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false);

                var baseNames = GetBaseNames(semanticModel, nameInfo);
                if (baseNames == default)
                {
                    return;
                }

                var recommendedNames = await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, cancellationToken).ConfigureAwait(false);

                var sortValue = 0;
                foreach (var(name, kind) in recommendedNames)
                {
                    // We've produced items in the desired order, add a sort text to each item to prevent alphabetization
                    completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8")));
                    sortValue++;
                }

                completionContext.SuggestionModeItem = CommonCompletionItem.Create(
                    CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default);
            }
            catch (Exception e) when(FatalError.ReportWithoutCrashUnlessCanceled(e))
            {
                // nop
            }
        }
예제 #7
0
            private static bool IsTypeParameterDeclaration(SyntaxToken token, SemanticModel semanticModel,
                                                           int position, CancellationToken cancellationToken, out NameDeclarationInfo result)
            {
                if (token.IsKind(SyntaxKind.LessThanToken, SyntaxKind.CommaToken) &&
                    token.Parent.IsKind(SyntaxKind.TypeParameterList))
                {
                    result = new NameDeclarationInfo(
                        ImmutableArray.Create(SymbolKind.TypeParameter),
                        Accessibility.NotApplicable,
                        new DeclarationModifiers(),
                        type: null);

                    return(true);
                }

                result = default(NameDeclarationInfo);
                return(false);
            }
예제 #8
0
            private static bool IsPossibleOutVariableDeclaration(SyntaxToken token, SemanticModel semanticModel, int position,
                                                                 ITypeInferenceService typeInferenceService, CancellationToken cancellationToken, out NameDeclarationInfo result)
            {
                if (!token.IsKind(SyntaxKind.IdentifierToken) || !(token.Parent.IsKind(SyntaxKind.IdentifierName)))
                {
                    result = default;
                    return(false);
                }

                var argument = token.Parent.Parent as ArgumentSyntax            // var is child of ArgumentSyntax, eg. Goo(out var $$
                               ?? token.Parent.Parent.Parent as ArgumentSyntax; // var is child of DeclarationExpression

                // under ArgumentSyntax, eg. Goo(out var a$$

                if (argument == null || !argument.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword))
                {
                    result = default;
                    return(false);
                }

                var type = typeInferenceService.InferType(semanticModel, argument.SpanStart, objectAsDefault: false, cancellationToken: cancellationToken);

                if (type != null)
                {
                    result = new NameDeclarationInfo(
                        ImmutableArray.Create(SymbolKind.Local),
                        Accessibility.NotApplicable,
                        new DeclarationModifiers(),
                        type,
                        alias: null);
                    return(true);
                }

                result = default;
                return(false);
            }
예제 #9
0
        public override async Task ProvideCompletionsAsync(CompletionContext completionContext)
        {
            var position          = completionContext.Position;
            var document          = completionContext.Document;
            var cancellationToken = completionContext.CancellationToken;
            var semanticModel     = await document.GetSemanticModelForSpanAsync(new Text.TextSpan(position, 0), cancellationToken).ConfigureAwait(false);

            var context = CSharpSyntaxContext.CreateContext(document.Project.Solution.Workspace, semanticModel, position, cancellationToken);

            if (context.IsInNonUserCode)
            {
                return;
            }

            var nameInfo = await NameDeclarationInfo.GetDeclarationInfo(document, position, cancellationToken).ConfigureAwait(false);

            if (!IsValidType(nameInfo.Type))
            {
                return;
            }

            var type             = UnwrapType(nameInfo.Type, semanticModel.Compilation);
            var baseNames        = NameGenerator.GetBaseNames(type);
            var recommendedNames = await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, cancellationToken).ConfigureAwait(false);

            int sortValue = 0;

            foreach (var(name, kind) in recommendedNames)
            {
                // We've produced items in the desired order, add a sort text to each item to prevent alphabetization
                completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8")));
                sortValue++;
            }

            completionContext.SuggestionModeItem = CommonCompletionItem.Create(CSharpFeaturesResources.Name, CompletionItemRules.Default);
        }
        public override async Task ProvideCompletionsAsync(CompletionContext completionContext)
        {
            try
            {
                var position          = completionContext.Position;
                var document          = completionContext.Document;
                var cancellationToken = completionContext.CancellationToken;
                var semanticModel     = await document.ReuseExistingSpeculativeModelAsync(position, cancellationToken).ConfigureAwait(false);

                if (!completionContext.CompletionOptions.ShowNameSuggestions)
                {
                    return;
                }

                var context = CSharpSyntaxContext.CreateContext(document, semanticModel, position, cancellationToken);
                if (context.IsInNonUserCode)
                {
                    return;
                }

                var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false);

                using var _ = ArrayBuilder <(string name, SymbolKind kind)> .GetInstance(out var result);

                // Suggest names from existing overloads.
                if (nameInfo.PossibleSymbolKinds.Any(k => k.SymbolKind == SymbolKind.Parameter))
                {
                    var(_, partialSemanticModel) = await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                    if (partialSemanticModel is not null)
                    {
                        AddNamesFromExistingOverloads(context, partialSemanticModel, result, cancellationToken);
                    }
                }

                var baseNames = GetBaseNames(semanticModel, nameInfo);
                if (baseNames != default)
                {
                    await GetRecommendedNamesAsync(baseNames, nameInfo, context, document, result, cancellationToken).ConfigureAwait(false);
                }

                var recommendedNames = result.ToImmutable();

                if (recommendedNames.IsEmpty)
                {
                    return;
                }

                var sortValue = 0;
                foreach (var(name, kind) in recommendedNames)
                {
                    // We've produced items in the desired order, add a sort text to each item to prevent alphabetization
                    completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8")));
                    sortValue++;
                }

                completionContext.SuggestionModeItem = CommonCompletionItem.Create(
                    CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default);
            }
            catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, ErrorSeverity.General))
            {
                // nop
            }
        }
예제 #11
0
            private static bool IsMethodDeclaration(SyntaxToken token, SemanticModel semanticModel,
                                                    int position, CancellationToken cancellationToken, out NameDeclarationInfo result)
            {
                result = IsLastTokenOfType <MethodDeclarationSyntax>(
                    token,
                    semanticModel,
                    m => m.ReturnType,
                    m => m.Modifiers,
                    GetPossibleDeclarations,
                    cancellationToken);

                return(result.Type != null);
            }
예제 #12
0
 private static bool IsParameterDeclaration(SyntaxToken token, SemanticModel semanticModel,
                                            int position, CancellationToken cancellationToken, out NameDeclarationInfo result)
 {
     result = IsLastTokenOfType <ParameterSyntax>(
         token, semanticModel,
         p => p.Type,
         _ => default(SyntaxTokenList),
         _ => ImmutableArray.Create(SymbolKind.Parameter),
         cancellationToken);
     return(result.Type != null);
 }
예제 #13
0
 private static bool IsVariableDeclaration(SyntaxToken token, SemanticModel semanticModel,
                                           int position, CancellationToken cancellationToken, out NameDeclarationInfo result)
 {
     result = IsFollowingTypeOrComma <VariableDeclarationSyntax>(token, semanticModel,
                                                                 v => v.Type,
                                                                 v => v.Parent is LocalDeclarationStatementSyntax l ? l.Modifiers : default(SyntaxTokenList?),
                                                                 d => ImmutableArray.Create(SymbolKind.Local),
                                                                 cancellationToken);
     return(result.Type != null);
 }
예제 #14
0
 private static bool IsIncompleteMemberDeclaration(SyntaxToken token, SemanticModel semanticModel,
                                                   int position, CancellationToken cancellationToken, out NameDeclarationInfo result)
 {
     result = IsLastTokenOfType <IncompleteMemberSyntax>(token, semanticModel,
                                                         i => i.Type,
                                                         i => i.Modifiers,
                                                         GetPossibleDeclarations,
                                                         cancellationToken);
     return(result.Type != null);
 }
예제 #15
0
 private static bool IsFieldDeclaration(SyntaxToken token, SemanticModel semanticModel,
                                        int position, CancellationToken cancellationToken, out NameDeclarationInfo result)
 {
     result = IsFollowingTypeOrComma <VariableDeclarationSyntax>(token, semanticModel,
                                                                 v => v.Type,
                                                                 v => v.Parent is FieldDeclarationSyntax f ? f.Modifiers : default(SyntaxTokenList?),
                                                                 GetPossibleDeclarations,
                                                                 cancellationToken);
     return(result.Type != null);
 }
예제 #16
0
        public override async Task ProvideCompletionsAsync(CompletionContext completionContext)
        {
            try
            {
                var position          = completionContext.Position;
                var document          = completionContext.Document;
                var cancellationToken = completionContext.CancellationToken;

                if (!completionContext.CompletionOptions.ShowNameSuggestions)
                {
                    return;
                }

                var context = (CSharpSyntaxContext)await completionContext.GetSyntaxContextWithExistingSpeculativeModelAsync(document, cancellationToken).ConfigureAwait(false);

                if (context.IsInNonUserCode)
                {
                    return;
                }

                // Do not show name suggestions for unbound "async" identifier.
                // Most likely user is writing an async method, so name suggestion will just interfere him
                if (context.TargetToken.IsKindOrHasMatchingText(SyntaxKind.AsyncKeyword) &&
                    context.SemanticModel.GetSymbolInfo(context.TargetToken).GetAnySymbol() is null)
                {
                    return;
                }

                var nameInfo = await NameDeclarationInfo.GetDeclarationInfoAsync(document, position, cancellationToken).ConfigureAwait(false);

                using var _ = ArrayBuilder <(string name, SymbolKind kind)> .GetInstance(out var result);

                // Suggest names from existing overloads.
                if (nameInfo.PossibleSymbolKinds.Any(k => k.SymbolKind == SymbolKind.Parameter))
                {
                    var(_, partialSemanticModel) = await document.GetPartialSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                    if (partialSemanticModel is not null)
                    {
                        AddNamesFromExistingOverloads(context, partialSemanticModel, result, cancellationToken);
                    }
                }

                var baseNames = GetBaseNames(context.SemanticModel, nameInfo);
                if (baseNames != default)
                {
                    var namingStyleOptions = await document.GetNamingStylePreferencesAsync(completionContext.CompletionOptions.NamingStyleFallbackOptions, cancellationToken).ConfigureAwait(false);

                    GetRecommendedNames(baseNames, nameInfo, context, result, namingStyleOptions, cancellationToken);
                }

                var recommendedNames = result.ToImmutable();

                if (recommendedNames.IsEmpty)
                {
                    return;
                }

                var sortValue = 0;
                foreach (var(name, kind) in recommendedNames)
                {
                    // We've produced items in the desired order, add a sort text to each item to prevent alphabetization
                    completionContext.AddItem(CreateCompletionItem(name, GetGlyph(kind, nameInfo.DeclaredAccessibility), sortValue.ToString("D8")));
                    sortValue++;
                }

                completionContext.SuggestionModeItem = CommonCompletionItem.Create(
                    CSharpFeaturesResources.Name, displayTextSuffix: "", CompletionItemRules.Default);
            }
            catch (Exception e) when(FatalError.ReportAndCatchUnlessCanceled(e, ErrorSeverity.General))
            {
                // nop
            }
        }