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)); }
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); }
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); }
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); }
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); } }
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); } } }
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); }
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 ) ); }
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); } }
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++; } }
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); } }
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); }
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)); }
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); }
public static SymbolResult <T> Create <T>(string desiredName, TSimpleNameSyntax nameNode, T symbol, double weight) where T : ISymbol => new(desiredName, nameNode, symbol, weight);