protected bool ExpressionBinds(SearchScope searchScope, TSimpleNameSyntax nameNode, bool checkForExtensionMethods)
            {
                // See if the name binds to something other then the error type. If it does, there's nothing further we need to do.
                // For extension methods, however, we will continue to search if there exists any better matched method.
                searchScope.CancellationToken.ThrowIfCancellationRequested();
                var symbolInfo = _semanticModel.GetSymbolInfo(nameNode, searchScope.CancellationToken);

                if (symbolInfo.CandidateReason == CandidateReason.OverloadResolutionFailure && !checkForExtensionMethods)
                {
                    return(true);
                }

                return(symbolInfo.Symbol != null);
            }
            private void HandleNugetReference(
                string source,
                ArrayBuilder <Reference> allReferences,
                TSimpleNameSyntax nameNode,
                bool isAttributeSearch,
                PackageWithTypeResult result,
                int weight)
            {
                var desiredName = GetDesiredName(isAttributeSearch, result.TypeName);

                allReferences.Add(new PackageReference(_owner,
                                                       new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames.ToReadOnlyList(), weight),
                                                       source, result.PackageName, result.Version));
            }
コード例 #3
0
            public async Task <ImmutableArray <SymbolResult <ISymbol> > > FindDeclarationsAsync(
                string name,
                TSimpleNameSyntax nameNode,
                SymbolFilter filter
                )
            {
                if (name != null && string.IsNullOrWhiteSpace(name))
                {
                    return(ImmutableArray <SymbolResult <ISymbol> > .Empty);
                }

                using var query = Exact
                    ? SearchQuery.Create(name, ignoreCase: true)
                    : SearchQuery.CreateFuzzy(name);
                var symbols = await FindDeclarationsAsync(filter, query).ConfigureAwait(false);

                if (Exact)
                {
                    // We did an exact, case insensitive, search.  Case sensitive matches should
                    // be preferred though over insensitive ones.
                    return(symbols.SelectAsArray(
                               s =>
                               SymbolResult.Create(s.Name, nameNode, s, weight: s.Name == name ? 0 : 1)
                               ));
                }

                // TODO(cyrusn): It's a shame we have to compute this twice.  However, there's no
                // great way to store the original value we compute because it happens deep in the
                // compiler bowels when we call FindDeclarations.
                var similarityChecker = WordSimilarityChecker.Allocate(
                    name,
                    substringsAreSimilar: false
                    );

                var result = symbols.SelectAsArray(
                    s =>
                {
                    var areSimilar = similarityChecker.AreSimilar(s.Name, out var matchCost);

                    Debug.Assert(areSimilar);
                    return(SymbolResult.Create(s.Name, nameNode, s, matchCost));
                }
                    );

                similarityChecker.Free();

                return(result);
            }
コード例 #4
0
            private async Task FindNugetOrReferenceAssemblyTypeReferencesAsync(
                List <Reference> allReferences, TSimpleNameSyntax nameNode,
                string name, int arity, bool inAttributeContext,
                CancellationToken cancellationToken)
            {
                if (arity == 0 && inAttributeContext)
                {
                    await FindNugetOrReferenceAssemblyTypeReferencesWorkerAsync(
                        allReferences, nameNode, name + AttributeSuffix, arity,
                        isAttributeSearch : true, cancellationToken : cancellationToken).ConfigureAwait(false);
                }

                await FindNugetOrReferenceAssemblyTypeReferencesWorkerAsync(
                    allReferences, nameNode, name, arity,
                    isAttributeSearch : false, cancellationToken : cancellationToken).ConfigureAwait(false);
            }
コード例 #5
0
ファイル: SymbolReferenceFinder.cs プロジェクト: belav/roslyn
            private static void CalculateContext(
                TSimpleNameSyntax nameNode,
                ISyntaxFactsService syntaxFacts,
                out string name,
                out int arity,
                out bool inAttributeContext,
                out bool hasIncompleteParentMember,
                out bool looksGeneric
                )
            {
                // Has to be a simple identifier or generic name.
                syntaxFacts.GetNameAndArityOfSimpleName(nameNode, out name, out arity);

                inAttributeContext        = syntaxFacts.IsAttributeName(nameNode);
                hasIncompleteParentMember = syntaxFacts.HasIncompleteParentMember(nameNode);
                looksGeneric = syntaxFacts.LooksGeneric(nameNode);
            }
コード例 #6
0
            private async Task FindNugetOrReferenceAssemblyTypeReferencesWorkerAsync(
                ArrayBuilder <Reference> allReferences, TSimpleNameSyntax nameNode,
                string name, int arity, bool isAttributeSearch, CancellationToken cancellationToken)
            {
                if (_searchReferenceAssemblies)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    await FindReferenceAssemblyTypeReferencesAsync(
                        allReferences, nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
                }

                foreach (var packageSource in _packageSources)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    await FindNugetTypeReferencesAsync(
                        packageSource, allReferences,
                        nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
                }
            }
コード例 #7
0
            private async Task FindNugetOrReferenceAssemblyTypeReferencesWorkerAsync(
                List <Reference> allReferences, TSimpleNameSyntax nameNode,
                string name, int arity, bool isAttributeSearch, CancellationToken cancellationToken)
            {
                var workspaceServices = _document.Project.Solution.Workspace.Services;
                var searchService     = _owner._packageSearchService ?? workspaceServices.GetService <IPackageSearchService>();
                var installerService  = _owner._packageInstallerService ?? workspaceServices.GetService <IPackageInstallerService>();

                if (searchService != null && installerService != null && installerService.IsEnabled)
                {
                    foreach (var packageSource in installerService.PackageSources)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        await FindNugetOrReferenceAssemblyTypeReferencesAsync(
                            packageSource, searchService, installerService, allReferences,
                            nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
コード例 #8
0
            private Task HandleNugetReferenceAsync(
                string source,
                IPackageInstallerService installerService,
                List <Reference> allReferences,
                TSimpleNameSyntax nameNode,
                Project project,
                bool isAttributeSearch,
                PackageWithTypeResult result,
                int weight)
            {
                if (!installerService.IsInstalled(project.Solution.Workspace, project.Id, result.PackageName))
                {
                    var desiredName = GetDesiredName(isAttributeSearch, result.TypeName);
                    allReferences.Add(new PackageReference(_owner, installerService,
                                                           new SearchResult(desiredName, nameNode, result.ContainingNamespaceNames, weight),
                                                           source, result.PackageName, result.Version));
                }

                return(SpecializedTasks.EmptyTask);
            }
コード例 #9
0
            private async Task HandleReferenceAssemblyReferenceAsync(
                ArrayBuilder <Reference> allReferences,
                TSimpleNameSyntax nameNode,
                Project project,
                bool isAttributeSearch,
                ReferenceAssemblyWithTypeResult result,
                int weight,
                CancellationToken cancellationToken
                )
            {
                foreach (var reference in project.MetadataReferences)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var compilation = await project
                                      .GetRequiredCompilationAsync(cancellationToken)
                                      .ConfigureAwait(false);

                    var assemblySymbol =
                        compilation.GetAssemblyOrModuleSymbol(reference) as IAssemblySymbol;
                    if (assemblySymbol?.Name == result.AssemblyName)
                    {
                        // Project already has a reference to an assembly with this name.
                        return;
                    }
                }

                var desiredName = GetDesiredName(isAttributeSearch, result.TypeName);

                allReferences.Add(
                    new AssemblyReference(
                        _owner,
                        new SearchResult(
                            desiredName,
                            nameNode,
                            result.ContainingNamespaceNames.ToReadOnlyList(),
                            weight
                            ),
                        result
                        )
                    );
            }
コード例 #10
0
            private async Task FindNugetTypeReferencesAsync(
                PackageSource source,
                ArrayBuilder <Reference> allReferences,
                TSimpleNameSyntax nameNode,
                string name,
                int arity,
                bool isAttributeSearch,
                CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var results = await _symbolSearchService.FindPackagesWithTypeAsync(
                    source.Name, name, arity, cancellationToken).ConfigureAwait(false);

                foreach (var result in results)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    HandleNugetReference(
                        source.Source, allReferences, nameNode,
                        isAttributeSearch, result,
                        weight: allReferences.Count);
                }
            }
コード例 #11
0
            private async Task FindNugetOrReferenceAssemblyTypeReferencesAsync(
                PackageSource source,
                IPackageSearchService searchService,
                IPackageInstallerService installerService,
                List <Reference> allReferences,
                TSimpleNameSyntax nameNode,
                string name,
                int arity,
                bool isAttributeSearch,
                CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var results = searchService.FindPackagesWithType(source.Name, name, arity, cancellationToken);

                var project   = _document.Project;
                var projectId = project.Id;
                var workspace = project.Solution.Workspace;

                int weight = 0;

                foreach (var result in results)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    if (result.IsDesktopFramework)
                    {
                        await HandleReferenceAssemblyReferenceAsync(
                            installerService, allReferences, nameNode, project,
                            isAttributeSearch, result, weight, cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        await HandleNugetReferenceAsync(
                            source.Source, installerService, allReferences, nameNode,
                            project, isAttributeSearch, result, weight).ConfigureAwait(false);
                    }

                    weight++;
                }
            }
コード例 #12
0
            private async Task FindNugetOrReferenceAssemblyTypeReferencesWorkerAsync(
                ArrayBuilder <Reference> allReferences, TSimpleNameSyntax nameNode,
                string name, int arity, bool isAttributeSearch, CancellationToken cancellationToken)
            {
                var workspaceServices = _document.Project.Solution.Workspace.Services;

                var symbolSearchService = _owner._symbolSearchService ?? workspaceServices.GetService <ISymbolSearchService>();
                var installerService    = _owner._packageInstallerService ?? workspaceServices.GetService <IPackageInstallerService>();

                var language = _document.Project.Language;

                var options = workspaceServices.Workspace.Options;
                var searchReferenceAssemblies = options.GetOption(
                    SymbolSearchOptions.SuggestForTypesInReferenceAssemblies, language);
                var searchNugetPackages = options.GetOption(
                    SymbolSearchOptions.SuggestForTypesInNuGetPackages, language);

                if (symbolSearchService != null &&
                    searchReferenceAssemblies)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    await FindReferenceAssemblyTypeReferencesAsync(
                        symbolSearchService, allReferences, nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
                }

                if (symbolSearchService != null &&
                    installerService != null &&
                    searchNugetPackages &&
                    installerService.IsEnabled)
                {
                    foreach (var packageSource in installerService.PackageSources)
                    {
                        cancellationToken.ThrowIfCancellationRequested();
                        await FindNugetTypeReferencesAsync(
                            packageSource, symbolSearchService, installerService, allReferences,
                            nameNode, name, arity, isAttributeSearch, cancellationToken).ConfigureAwait(false);
                    }
                }
            }
            private async Task FindReferenceAssemblyTypeReferencesAsync(
                ArrayBuilder <Reference> allReferences,
                TSimpleNameSyntax nameNode,
                string name,
                int arity,
                bool isAttributeSearch,
                CancellationToken cancellationToken)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var results = await _symbolSearchService.FindReferenceAssembliesWithTypeAsync(
                    name, arity, cancellationToken).ConfigureAwait(false);

                var project = _document.Project;

                foreach (var result in results)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    await HandleReferenceAssemblyReferenceAsync(
                        allReferences, nameNode, project,
                        isAttributeSearch, result, weight : allReferences.Count,
                        cancellationToken : cancellationToken).ConfigureAwait(false);
                }
            }
コード例 #14
0
            private bool TryInitializeSimpleName(
                TService service,
                SemanticDocument document,
                TSimpleNameSyntax simpleName,
                CancellationToken cancellationToken)
            {
                if (!service.TryInitializeIdentifierNameState(
                        document, simpleName, cancellationToken,
                        out var identifierToken, out var simpleNameOrMemberAccessExpression, out var isInExecutableBlock, out var isInConditionalAccessExpression))
                {
                    return(false);
                }

                if (string.IsNullOrWhiteSpace(identifierToken.ValueText))
                {
                    return(false);
                }

                this.SimpleNameOpt   = simpleName;
                this.IdentifierToken = identifierToken;
                this.SimpleNameOrMemberAccessExpressionOpt = simpleNameOrMemberAccessExpression;
                this.IsInExecutableBlock             = isInExecutableBlock;
                this.IsInConditionalAccessExpression = isInConditionalAccessExpression;

                // If we're in a type context then we shouldn't offer to generate a field or
                // property.
                var syntaxFacts = document.Project.LanguageServices.GetService <ISyntaxFactsService>();

                if (syntaxFacts.IsInNamespaceOrTypeContext(this.SimpleNameOrMemberAccessExpressionOpt))
                {
                    return(false);
                }

                this.IsConstant = syntaxFacts.IsInConstantContext(this.SimpleNameOrMemberAccessExpressionOpt);

                // If we're not in a type, don't even bother.  NOTE(cyrusn): We'll have to rethink this
                // for C# Script.
                cancellationToken.ThrowIfCancellationRequested();
                var semanticModel = document.SemanticModel;

                this.ContainingType = semanticModel.GetEnclosingNamedType(this.IdentifierToken.SpanStart, cancellationToken);
                if (this.ContainingType == null)
                {
                    return(false);
                }

                // Now, try to bind the invocation and see if it succeeds or not.  if it succeeds and
                // binds uniquely, then we don't need to offer this quick fix.
                cancellationToken.ThrowIfCancellationRequested();
                var semanticInfo = semanticModel.GetSymbolInfo(this.SimpleNameOrMemberAccessExpressionOpt, cancellationToken);

                cancellationToken.ThrowIfCancellationRequested();
                if (semanticInfo.Symbol != null)
                {
                    return(false);
                }

                // Either we found no matches, or this was ambiguous. Either way, we might be able
                // to generate a method here.  Determine where the user wants to generate the method
                // into, and if it's valid then proceed.
                cancellationToken.ThrowIfCancellationRequested();
                if (!service.TryDetermineTypeToGenerateIn(document, this.ContainingType, this.SimpleNameOrMemberAccessExpressionOpt, cancellationToken,
                                                          out var typeToGenerateIn, out var isStatic))
                {
                    return(false);
                }

                this.TypeToGenerateIn = typeToGenerateIn;
                this.IsStatic         = isStatic;

                DetermineFieldType(document, cancellationToken);

                var semanticFacts = document.Project.LanguageServices.GetService <ISemanticFactsService>();

                this.IsInRefContext    = semanticFacts.IsInRefContext(semanticModel, this.SimpleNameOrMemberAccessExpressionOpt, cancellationToken);
                this.IsInInContext     = semanticFacts.IsInInContext(semanticModel, this.SimpleNameOrMemberAccessExpressionOpt, cancellationToken);
                this.IsInOutContext    = semanticFacts.IsInOutContext(semanticModel, this.SimpleNameOrMemberAccessExpressionOpt, cancellationToken);
                this.IsWrittenTo       = semanticFacts.IsWrittenTo(semanticModel, this.SimpleNameOrMemberAccessExpressionOpt, cancellationToken);
                this.IsOnlyWrittenTo   = semanticFacts.IsOnlyWrittenTo(semanticModel, this.SimpleNameOrMemberAccessExpressionOpt, cancellationToken);
                this.IsInConstructor   = DetermineIsInConstructor(document);
                this.IsInMemberContext = this.SimpleNameOpt != this.SimpleNameOrMemberAccessExpressionOpt ||
                                         syntaxFacts.IsObjectInitializerNamedAssignmentIdentifier(this.SimpleNameOrMemberAccessExpressionOpt);

                CheckSurroundingContext(document, SymbolKind.Field, cancellationToken);
                CheckSurroundingContext(document, SymbolKind.Property, cancellationToken);

                return(true);
            }
コード例 #15
0
            public async Task <IEnumerable <SearchResult <ISymbol> > > FindDeclarationsAsync(string name, TSimpleNameSyntax nameNode, SymbolFilter filter)
            {
                if (name != null && string.IsNullOrWhiteSpace(name))
                {
                    return(SpecializedCollections.EmptyEnumerable <SearchResult <ISymbol> >());
                }

                var query   = this.Exact ? SearchQuery.Create(name, ignoreCase: true) : SearchQuery.CreateFuzzy(name);
                var symbols = await FindDeclarationsAsync(name, filter, query).ConfigureAwait(false);

                if (Exact)
                {
                    // We did an exact, case insensitive, search.  Case sensitive matches should
                    // be preffered though over insensitive ones.
                    return(symbols.Select(s => SearchResult.Create(s.Name, nameNode, s, weight: s.Name == name ? 0 : 1)).ToList());
                }

                // TODO(cyrusn): It's a shame we have to compute this twice.  However, there's no
                // great way to store the original value we compute because it happens deep in the
                // compiler bowels when we call FindDeclarations.
                using (var similarityChecker = new WordSimilarityChecker(name))
                {
                    return(symbols.Select(s =>
                    {
                        double matchCost;
                        var areSimilar = similarityChecker.AreSimilar(s.Name, out matchCost);

                        Debug.Assert(areSimilar);
                        return SearchResult.Create(s.Name, nameNode, s, matchCost);
                    }).ToList());
                }
            }
            private Task <IEnumerable <SearchResult <ISymbol> > > GetSymbolsAsync(SearchScope searchScope, TSimpleNameSyntax nameNode)
            {
                searchScope.CancellationToken.ThrowIfCancellationRequested();

                // See if the name binds.  If it does, there's nothing further we need to do.
                if (ExpressionBinds(searchScope, nameNode, checkForExtensionMethods: true))
                {
                    return(SpecializedTasks.EmptyEnumerable <SearchResult <ISymbol> >());
                }

                string name;
                int    arity;

                _syntaxFacts.GetNameAndArityOfSimpleName(nameNode, out name, out arity);
                if (name == null)
                {
                    return(SpecializedTasks.EmptyEnumerable <SearchResult <ISymbol> >());
                }

                return(searchScope.FindDeclarationsAsync(name, nameNode, SymbolFilter.Member));
            }
コード例 #17
0
            private bool TryInitializeIdentifierName(
                TService service,
                SemanticDocument semanticDocument,
                TSimpleNameSyntax identifierName,
                CancellationToken cancellationToken)
            {
                this.SimpleName = identifierName;
                if (!service.TryInitializeIdentifierNameState(semanticDocument, identifierName, cancellationToken,
                                                              out var identifierToken, out var simpleNameOrMemberAccessExpression))
                {
                    return(false);
                }

                this.IdentifierToken = identifierToken;
                this.SimpleNameOrMemberAccessExpression = simpleNameOrMemberAccessExpression;

                var semanticModel = semanticDocument.SemanticModel;
                var semanticFacts = semanticDocument.Document.GetLanguageService <ISemanticFactsService>();
                var syntaxFacts   = semanticDocument.Document.GetLanguageService <ISyntaxFactsService>();

                if (semanticFacts.IsWrittenTo(semanticModel, this.SimpleNameOrMemberAccessExpression, cancellationToken) ||
                    syntaxFacts.IsInNamespaceOrTypeContext(this.SimpleNameOrMemberAccessExpression))
                {
                    return(false);
                }

                // Now, try to bind the invocation and see if it succeeds or not.  if it succeeds and
                // binds uniquely, then we don't need to offer this quick fix.
                cancellationToken.ThrowIfCancellationRequested();
                var containingType = semanticModel.GetEnclosingNamedType(identifierToken.SpanStart, cancellationToken);

                if (containingType == null)
                {
                    return(false);
                }

                var semanticInfo = semanticModel.GetSymbolInfo(this.SimpleNameOrMemberAccessExpression, cancellationToken);

                if (cancellationToken.IsCancellationRequested)
                {
                    return(false);
                }

                if (semanticInfo.Symbol != null)
                {
                    return(false);
                }
                // Either we found no matches, or this was ambiguous. Either way, we might be able
                // to generate a method here.  Determine where the user wants to generate the method
                // into, and if it's valid then proceed.
                if (!service.TryDetermineTypeToGenerateIn(
                        semanticDocument, containingType, simpleNameOrMemberAccessExpression, cancellationToken,
                        out var typeToGenerateIn, out var isStatic))
                {
                    return(false);
                }

                if (!isStatic)
                {
                    return(false);
                }

                this.TypeToGenerateIn = typeToGenerateIn;
                return(true);
            }
コード例 #18
0
 public static SymbolResult <T> Create <T>(string desiredName, TSimpleNameSyntax nameNode, T symbol, double weight) where T : ISymbol
 => new(desiredName, nameNode, symbol, weight);