예제 #1
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());
                }
            }
예제 #2
0
        public void TestCloseMatch()
        {
            Assert.True(WordSimilarityChecker.AreSimilar("variabledeclaratorsyntax", "variabledeclaratorsyntaxextensions"));

            Assert.True(WordSimilarityChecker.AreSimilar("expressionsyntax", "expressionsyntaxextensions"));
            Assert.True(WordSimilarityChecker.AreSimilar("expressionsyntax", "expressionsyntaxgeneratorvisitor"));
        }
예제 #3
0
        private async Task CheckItemsAsync(
            CodeFixContext context, SyntaxToken nameToken, bool isGeneric,
            CompletionList completionList, WordSimilarityChecker similarityChecker)
        {
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;

            var onlyConsiderGenerics = isGeneric;
            var results = new MultiDictionary <double, string>();

            foreach (var item in completionList.ItemsList)
            {
                if (onlyConsiderGenerics && !IsGeneric(item))
                {
                    continue;
                }

                var candidateText = item.FilterText;
                if (!similarityChecker.AreSimilar(candidateText, out var matchCost))
                {
                    continue;
                }

                var insertionText = await GetInsertionTextAsync(document, item, cancellationToken : cancellationToken).ConfigureAwait(false);

                results.Add(matchCost, insertionText);
            }

            var nameText    = nameToken.ValueText;
            var codeActions = results.OrderBy(kvp => kvp.Key)
                              .SelectMany(kvp => kvp.Value.Order())
                              .Where(t => t != nameText)
                              .Take(3)
                              .Select(n => CreateCodeAction(nameToken, nameText, n, document))
                              .ToImmutableArrayOrEmpty <CodeAction>();

            if (codeActions.Length > 1)
            {
                // Wrap the spell checking actions into a single top level suggestion
                // so as to not clutter the list.
                context.RegisterCodeFix(
                    CodeAction.CreateWithPriority(
                        CodeActionPriority.Low,
                        string.Format(FeaturesResources.Fix_typo_0, nameText),
                        codeActions,
                        isInlinable: true),
                    context.Diagnostics);
            }
            else
            {
                context.RegisterFixes(codeActions, context.Diagnostics);
            }
        }
        private async Task CreateSpellCheckCodeIssueAsync(CodeFixContext context, TSimpleName nameNode, string nameText, CancellationToken cancellationToken)
        {
            var document = context.Document;
            var service  = CompletionService.GetService(document);

            // Disable snippets from ever appearing in the completion items. It's
            // very unlikely the user would ever mispell a snippet, then use spell-
            // checking to fix it, then try to invoke the snippet.
            var originalOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

            var options = originalOptions.WithChangedOption(CompletionOptions.SnippetsBehavior, document.Project.Language, SnippetsRule.NeverInclude);

            var completionList = await service.GetCompletionsAsync(
                document, nameNode.SpanStart, options : options, cancellationToken : cancellationToken).ConfigureAwait(false);

            if (completionList == null)
            {
                return;
            }

            var onlyConsiderGenerics = IsGeneric(nameNode);
            var results = new MultiDictionary <double, string>();

            using (var similarityChecker = new WordSimilarityChecker(nameText, substringsAreSimilar: true))
            {
                foreach (var item in completionList.Items)
                {
                    if (onlyConsiderGenerics && !IsGeneric(item))
                    {
                        continue;
                    }

                    var    candidateText = item.FilterText;
                    double matchCost;
                    if (!similarityChecker.AreSimilar(candidateText, out matchCost))
                    {
                        continue;
                    }

                    var insertionText = await GetInsertionTextAsync(document, item, cancellationToken : cancellationToken).ConfigureAwait(false);

                    results.Add(matchCost, insertionText);
                }
            }

            var matches = results.OrderBy(kvp => kvp.Key)
                          .SelectMany(kvp => kvp.Value.Order())
                          .Where(t => t != nameText)
                          .Take(3)
                          .Select(n => CreateCodeAction(nameNode, nameText, n, document));

            context.RegisterFixes(matches, context.Diagnostics);
        }
예제 #5
0
        public void TestNotCloseMatch()
        {
            Assert.False(WordSimilarityChecker.AreSimilar("propertyblocksyntax", "ipropertysymbol"));
            Assert.False(WordSimilarityChecker.AreSimilar("propertyblocksyntax", "ipropertysymbolextensions"));
            Assert.False(WordSimilarityChecker.AreSimilar("propertyblocksyntax", "typeblocksyntaxextensions"));

            Assert.False(WordSimilarityChecker.AreSimilar("fielddeclarationsyntax", "declarationinfo"));
            Assert.False(WordSimilarityChecker.AreSimilar("fielddeclarationsyntax", "declarationcomputer"));
            Assert.False(WordSimilarityChecker.AreSimilar("fielddeclarationsyntax", "filelinepositionspan"));

            Assert.False(WordSimilarityChecker.AreSimilar("variabledeclaratorsyntax", "visualbasicdeclarationcomputer"));
            Assert.False(WordSimilarityChecker.AreSimilar("variabledeclaratorsyntax", "ilineseparatorservice"));

            Assert.False(WordSimilarityChecker.AreSimilar("expressionsyntax", "awaitexpressioninfo"));
        }
예제 #6
0
        private async Task CreateSpellCheckCodeIssueAsync(CodeFixContext context, TSimpleName nameNode, string nameText, CancellationToken cancellationToken)
        {
            var document       = context.Document;
            var service        = CompletionService.GetService(document);
            var completionList = await service.GetCompletionsAsync(
                document, nameNode.SpanStart, cancellationToken : cancellationToken).ConfigureAwait(false);

            if (completionList == null)
            {
                return;
            }

            var onlyConsiderGenerics = IsGeneric(nameNode);
            var results = new MultiDictionary <double, string>();

            using (var similarityChecker = new WordSimilarityChecker(nameText, substringsAreSimilar: true))
            {
                foreach (var item in completionList.Items)
                {
                    if (onlyConsiderGenerics && !IsGeneric(item))
                    {
                        continue;
                    }

                    var    candidateText = item.FilterText;
                    double matchCost;
                    if (!similarityChecker.AreSimilar(candidateText, out matchCost))
                    {
                        continue;
                    }

                    var insertionText = await GetInsertionTextAsync(document, item, cancellationToken : cancellationToken).ConfigureAwait(false);

                    results.Add(matchCost, insertionText);
                }
            }

            var matches = results.OrderBy(kvp => kvp.Key)
                          .SelectMany(kvp => kvp.Value.Order())
                          .Where(t => t != nameText)
                          .Take(3)
                          .Select(n => CreateCodeAction(nameNode, nameText, n, document));

            context.RegisterFixes(matches, context.Diagnostics);
        }