Example #1
0
        private Model(
            DisconnectedBufferGraph disconnectedBufferGraph,
            IList <CompletionItem> totalItems,
            IList <CompletionItem> filteredItems,
            CompletionItem selectedItem,
            bool isHardSelection,
            bool isUnique,
            bool useSuggestionCompletionMode,
            CompletionItem builder,
            CompletionItem defaultBuilder,
            CompletionTriggerInfo triggerInfo,
            ITrackingPoint commitSpanEndPoint,
            bool dismissIfEmpty)
        {
            Contract.ThrowIfNull(selectedItem);
            Contract.ThrowIfFalse(totalItems.Count != 0, "Must have at least one item.");
            Contract.ThrowIfFalse(filteredItems.Count != 0, "Must have at least one filtered item.");
            Contract.ThrowIfFalse(filteredItems.Contains(selectedItem) || defaultBuilder == selectedItem, "Selected item must be in filtered items.");

            _disconnectedBufferGraph         = disconnectedBufferGraph;
            this.TotalItems                  = totalItems;
            this.FilteredItems               = filteredItems;
            this.SelectedItem                = selectedItem;
            this.IsHardSelection             = isHardSelection;
            this.IsUnique                    = isUnique;
            this.UseSuggestionCompletionMode = useSuggestionCompletionMode;
            this.Builder                    = builder;
            this.DefaultBuilder             = defaultBuilder;
            this.TriggerInfo                = triggerInfo;
            this.CommitTrackingSpanEndPoint = commitSpanEndPoint;
            this.DismissIfEmpty             = dismissIfEmpty;
        }
        public void TestEnter()
        {
            const string markup = @"
class c { public int value {set; get; }}

class d
{
    void foo()
    {
       c foo = new c { v$$
    }
}";

            using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromFile(markup))
            {
                var hostDocument = workspace.Documents.Single();
                var position     = hostDocument.CursorPosition.Value;
                var document     = workspace.CurrentSolution.GetDocument(hostDocument.Id);
                var triggerInfo  = CompletionTriggerInfo.CreateTypeCharTriggerInfo('a');

                var completionList = GetCompletionList(document, position, triggerInfo);
                var item           = completionList.Items.First();

                var completionService = document.Project.LanguageServices.GetService <ICompletionService>();
                var completionRules   = completionService.GetCompletionRules();

                Assert.False(completionRules.SendEnterThroughToEditor(item, string.Empty, workspace.Options), "Expected false from SendEnterThroughToEditor()");
            }
        }
Example #3
0
        protected void VerifyCommitCharacters(string initialMarkup, string textTypedSoFar, char[] validChars, char[] invalidChars = null)
        {
            Assert.NotNull(validChars);
            invalidChars = invalidChars ?? new [] { 'x' };

            using (var workspace = CSharpWorkspaceFactory.CreateWorkspaceFromFile(initialMarkup))
            {
                var hostDocument = workspace.DocumentWithCursor;
                var documentId   = workspace.GetDocumentId(hostDocument);
                var document     = workspace.CurrentSolution.GetDocument(documentId);
                var position     = hostDocument.CursorPosition.Value;

                var completionList = GetCompletionList(document, position, CompletionTriggerInfo.CreateInvokeCompletionTriggerInfo());
                var item           = completionList.Items.First(i => i.DisplayText.StartsWith(textTypedSoFar));

                var completionService = document.Project.LanguageServices.GetService <ICompletionService>();
                var completionRules   = completionService.GetCompletionRules();

                foreach (var ch in validChars)
                {
                    Assert.True(completionRules.IsCommitCharacter(item, ch, textTypedSoFar), $"Expected '{ch}' to be a commit character");
                }

                foreach (var ch in invalidChars)
                {
                    Assert.False(completionRules.IsCommitCharacter(item, ch, textTypedSoFar), $"Expected '{ch}' NOT to be a commit character");
                }
            }
        }
        private void VerifyProviderCommitCheckResults(Document document, int position, string itemToCommit, string expectedCodeAfterCommit, char? commitCharOpt, string textTypedSoFar)
        {
            var textBuffer = WorkspaceFixture.Workspace.Documents.Single().TextBuffer;
            var textSnapshot = textBuffer.CurrentSnapshot.AsText();

            var items = GetCompletionList(document, position, CompletionTriggerInfo.CreateInvokeCompletionTriggerInfo()).Items;
            var firstItem = items.First(i => CompareItems(i.DisplayText, itemToCommit));

            var completionRules = GetCompletionRules(document);
            var commitChar = commitCharOpt ?? '\t';

            var text = document.GetTextAsync().Result;

            if (commitChar == '\t' || completionRules.IsCommitCharacter(firstItem, commitChar, textTypedSoFar))
            {
                var textChange = completionRules.GetTextChange(firstItem, commitChar, textTypedSoFar);

                // Adjust TextChange to include commit character, so long as it isn't TAB.
                if (commitChar != '\t')
                {
                    textChange = new TextChange(textChange.Span, textChange.NewText.TrimEnd(commitChar) + commitChar);
                }

                text = text.WithChanges(textChange);
            }
            else
            {
                // nothing was committed, but we should insert the commit character.
                var textChange = new TextChange(new TextSpan(firstItem.FilterSpan.End, 0), commitChar.ToString());
                text = text.WithChanges(textChange);
            }

            Assert.Equal(expectedCodeAfterCommit, text.ToString());
        }
Example #5
0
        private Model(
            DisconnectedBufferGraph disconnectedBufferGraph,
            IList <CompletionItem> totalItems,
            IList <CompletionItem> filteredItems,
            CompletionItem selectedItem,
            ImmutableArray <CompletionItemFilter> completionItemFilters,
            ImmutableDictionary <CompletionItemFilter, bool> filterState,
            IReadOnlyDictionary <CompletionItem, string> completionItemToFilterText,
            bool isHardSelection,
            bool isUnique,
            bool useSuggestionCompletionMode,
            CompletionItem builder,
            CompletionItem defaultBuilder,
            CompletionTriggerInfo triggerInfo,
            ITrackingPoint commitSpanEndPoint,
            bool dismissIfEmpty)
        {
            Contract.ThrowIfFalse(totalItems.Count != 0, "Must have at least one item.");

            _disconnectedBufferGraph        = disconnectedBufferGraph;
            this.TotalItems                 = totalItems;
            this.FilteredItems              = filteredItems;
            this.FilterState                = filterState;
            this.SelectedItem               = selectedItem;
            this.CompletionItemFilters      = completionItemFilters;
            this.CompletionItemToFilterText = completionItemToFilterText;
            this.IsHardSelection            = isHardSelection;
            this.IsUnique = isUnique;
            this.UseSuggestionCompletionMode = useSuggestionCompletionMode;
            this.Builder                    = builder;
            this.DefaultBuilder             = defaultBuilder;
            this.TriggerInfo                = triggerInfo;
            this.CommitTrackingSpanEndPoint = commitSpanEndPoint;
            this.DismissIfEmpty             = dismissIfEmpty;
        }
        public override Task <ICompletionDataList> HandleCodeCompletionAsync(CodeCompletionContext completionContext,
                                                                             CompletionTriggerInfo triggerInfo,
                                                                             CancellationToken token = default(CancellationToken))
        {
            if (triggerInfo.TriggerCharacter == null)
            {
                return(null);
            }

            if (completionContext.TriggerOffset > 1 &&
                (char.IsLetterOrDigit(Editor.GetCharAt(completionContext.TriggerOffset - 2)) ||
                 Editor.GetCharAt(completionContext.TriggerOffset - 2) == '_'))
            {
                return(null);
            }

            if (IsComment(completionContext) || IsString(completionContext))
            {
                return(null);
            }

            if (IsCommand(completionContext))
            {
                var list = new CompletionDataList(CMakeCompletionDataLists.Commands);
                list.TriggerWordLength = 1;

                return(Task.FromResult <ICompletionDataList> (list));
            }
            return(null);
        }
Example #7
0
        private bool TryInvokeSnippetCompletion(TabKeyCommandArgs args, ICompletionService completionService)
        {
            var subjectBuffer = args.SubjectBuffer;
            var caretPoint    = args.TextView.GetCaretPoint(subjectBuffer).Value.Position;

            var text = subjectBuffer.AsTextContainer().CurrentText;

            // Delete the ? and invoke completion
            Workspace workspace = null;

            if (Workspace.TryGetWorkspace(subjectBuffer.AsTextContainer(), out workspace))
            {
                var documentId = workspace.GetDocumentIdInCurrentContext(subjectBuffer.AsTextContainer());
                if (documentId != null)
                {
                    var document = workspace.CurrentSolution.GetDocument(documentId);
                    if (document != null)
                    {
                        var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

                        if (caretPoint >= 2 && text[caretPoint - 1] == '?' && QuestionMarkIsPrecededByIdentifierAndWhitespace(text, caretPoint - 2, syntaxFacts))
                        {
                            var textChange = new TextChange(TextSpan.FromBounds(caretPoint - 1, caretPoint), string.Empty);
                            workspace.ApplyTextChanges(documentId, textChange, CancellationToken.None);
                            this.StartNewModelComputation(completionService, CompletionTriggerInfo.CreateSnippetTriggerInfo(), filterItems: false);
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
 public IEnumerable <ISelectedCompletionData> GetCompletion(CompletionTriggerInfo trigger, int position)
 {
     if (trigger.TriggerCharacter == '.')
     {
         return(_simp.GetCompletionData());
     }
     return(null);
 }
Example #9
0
 private bool MatchesFilterText(
     CompletionItem item,
     string filterText,
     ICompletionRules completionRules,
     CompletionTriggerInfo triggerInfo,
     CompletionFilterReason reason)
 {
     return(completionRules.MatchesFilterText(item, filterText, triggerInfo, reason) ?? false);
 }
 public static async Task<CompletionList> GetCompletionListAsync(Document document, int position,
     CompletionTriggerInfo triggerInfo, OptionSet options = null,
     CancellationToken cancellationToken = default(CancellationToken))
 {
     var providers = GetCompletionListProviders(document);
     var list = await InnerCompletionService.GetCompletionListAsync(document, position, triggerInfo.Inner, options, providers,
         cancellationToken).ConfigureAwait(false);
     return list == null ? null : new CompletionList(list);
 }
        private async Task<IEnumerable<CompletionItem>> GetItemsAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            if (document == null)
            {
                return null;
            }

            return await GetItemsWorkerAsync(document, position, triggerInfo, cancellationToken).ConfigureAwait(false);
        }
 public IEnumerable <CompletionItemGroup> GetGroups(
     IDocument document,
     int position,
     CompletionTriggerInfo triggerInfo,
     IEnumerable <ICompletionProvider> completionProviders,
     CancellationToken cancellationToken)
 {
     return(InvokeWrappedMethod <IEnumerable <CompletionItemGroup> >(
                MethodBase.GetCurrentMethod(), document, position, triggerInfo, completionProviders, cancellationToken));
 }
Example #13
0
 private bool IsBetterFilterMatch(
     CompletionItem item,
     CompletionItem bestItem,
     string filterText,
     ICompletionRules completionRules,
     CompletionTriggerInfo triggerInfo,
     CompletionFilterReason filterReason)
 {
     return(completionRules.IsBetterFilterMatch(item, bestItem, filterText, triggerInfo, filterReason) ?? false);
 }
Example #14
0
        private bool StartNewModelComputation(ICompletionService completionService, CompletionTriggerInfo triggerInfo, bool filterItems, bool dismissIfEmptyAllowed = true)
        {
            AssertIsForeground();
            Contract.ThrowIfTrue(sessionOpt != null);

            if (this.TextView.Selection.Mode == TextSelectionMode.Box)
            {
                Trace.WriteLine("Box selection, cannot have completion");

                // No completion with multiple selection
                return(false);
            }

            // The caret may no longer be mappable into our subject buffer.
            var caret = TextView.GetCaretPoint(SubjectBuffer);

            if (!caret.HasValue)
            {
                Trace.WriteLine("Caret is not mappable to subject buffer, cannot have completion");

                return(false);
            }


            if (this.TextView.Caret.Position.VirtualBufferPosition.IsInVirtualSpace)
            {
                // Convert any virtual whitespace to real whitespace by doing an empty edit at the caret position.
                _editorOperationsFactoryService.GetEditorOperations(TextView).InsertText("");
            }

            var computation = new ModelComputation <Model>(this, PrioritizedTaskScheduler.AboveNormalInstance);

            this.sessionOpt = new Session(this, computation, GetCompletionRules(), Presenter.CreateSession(TextView, SubjectBuffer, null));

            var completionProviders = triggerInfo.TriggerReason == CompletionTriggerReason.Snippets
                ? GetSnippetCompletionProviders()
                : GetCompletionProviders();

            sessionOpt.ComputeModel(completionService, triggerInfo, GetOptions(), completionProviders);

            var filterReason = triggerInfo.TriggerReason == CompletionTriggerReason.BackspaceOrDeleteCommand
                ? CompletionFilterReason.BackspaceOrDelete
                : CompletionFilterReason.TypeChar;

            if (filterItems)
            {
                sessionOpt.FilterModel(filterReason, dismissIfEmptyAllowed: dismissIfEmptyAllowed);
            }
            else
            {
                sessionOpt.IdentifyBestMatchAndFilterToAllItems(filterReason, dismissIfEmptyAllowed: dismissIfEmptyAllowed);
            }

            return(true);
        }
        public async Task <IList <CompletionItem> > GetCompletion(CompletionTriggerInfo trigger, int position)
        {
            var groups = await CompletionService.GetCompletionItemGroupsAsync(
                GetCurrentDocument(), position, trigger).ConfigureAwait(false);

            if (groups == null)
            {
                return(new CompletionItem[0]);
            }
            return(groups.SelectMany(t => t.Items).ToArray());
        }
        public CompletionItemGroup GetGroup(SourceText text, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken = default(CancellationToken))
        {
            var items = this.GetItems(text, position, triggerInfo, cancellationToken);

            if (items == null || !items.Any())
            {
                return(null);
            }

            return(new CompletionItemGroup(items));
        }
        private CompletionItemGroup GetCompletionGroup(string markup)
        {
            var    provider = CreateProvider();
            string code;
            int    cursorPosition;

            MarkupTestFile.GetPosition(markup, out code, out cursorPosition);
            var document    = CreateDocument(code);
            var triggerInfo = CompletionTriggerInfo.CreateInvokeCompletionTriggerInfo();

            return(provider.GetGroupAsync(document, cursorPosition, triggerInfo, CancellationToken.None).Result);
        }
        protected OptionSet GetOptions(Document document, CompletionTriggerInfo triggerInfo, AbstractSyntaxContext context)
        {
            var optionService          = context.GetWorkspaceService <IOptionService>();
            var filterOutOfScopeLocals = !triggerInfo.IsDebugger;
            var hideAdvancedMembers    = document.ShouldHideAdvancedMembers();
            var options = optionService
                          .GetOptions()
                          .WithChangedOption(RecommendationOptions.FilterOutOfScopeLocals, context.SemanticModel.Language, filterOutOfScopeLocals)
                          .WithChangedOption(RecommendationOptions.HideAdvancedMembers, context.SemanticModel.Language, hideAdvancedMembers);

            return(options);
        }
Example #19
0
        bool ShouldTriggerCompletionOnCharTyped(
            WordAtPosition word,
            CodeCompletionContext completionContext,
            CompletionTriggerInfo triggerInfo)
        {
            if (session.IsCompletionTriggerCharacter(triggerInfo.TriggerCharacter))
            {
                return(true);
            }

            return(ShouldTriggerCompletionAtPosition(word, completionContext));
        }
            private bool IsHardSelection(
                Model model,
                CompletionItem bestFilterMatch,
                ITextSnapshot textSnapshot,
                IList <ICompletionRules> completionRulesList,
                CompletionTriggerInfo triggerInfo,
                CompletionFilterReason reason)
            {
                if (model.Builder != null)
                {
                    return(bestFilterMatch != null && bestFilterMatch.DisplayText == model.Builder.DisplayText);
                }

                if (bestFilterMatch == null || model.UseSuggestionCompletionMode)
                {
                    return(false);
                }

                // We don't have a builder and we have a best match.  Normally this will be hard
                // selected, except for a few cases.  Specifically, if no filter text has been
                // provided, and this is not a preselect match then we will soft select it.  This
                // happens when the completion list comes up implicitly and there is something in
                // the MRU list.  In this case we do want to select it, but not with a hard
                // selection.  Otherwise you can end up with the following problem:
                //
                //  dim i as integer =<space>
                //
                // Completion will comes up after = with 'integer' selected (Because of MRU).  We do
                // not want 'space' to commit this.
                var viewSpan       = model.GetSubjectBufferFilterSpanInViewBuffer(bestFilterMatch.FilterSpan);
                var fullFilterText = model.GetCurrentTextInSnapshot(viewSpan, textSnapshot, endPoint: null);

                foreach (var completionRules in completionRulesList)
                {
                    var shouldSoftSelect = completionRules.ShouldSoftSelectItem(GetExternallyUsableCompletionItem(bestFilterMatch), fullFilterText, triggerInfo);
                    if (shouldSoftSelect == true)
                    {
                        return(false);
                    }
                }

                // If the user moved the caret left after they started typing, the 'best' match may not match at all
                // against the full text span that this item would be replacing.
                if (!MatchesFilterText(bestFilterMatch, fullFilterText, completionRulesList, triggerInfo, reason))
                {
                    return(false);
                }

                // There was either filter text, or this was a preselect match.  In either case, we
                // can hard select this.
                return(true);
            }
        protected override async Task <IEnumerable <CompletionItem> > GetItemsWorkerAsync(
            Document document, int position, CompletionTriggerInfo triggerInfo,
            CancellationToken cancellationToken)
        {
            using (Logger.LogBlock(FunctionId.Completion_SymbolCompletionProvider_GetItemsWorker, cancellationToken))
            {
                var regularItems = await GetItemsWorkerAsync(document, position, triggerInfo, preselect : false, cancellationToken : cancellationToken).ConfigureAwait(false);

                var preselectedItems = await GetItemsWorkerAsync(document, position, triggerInfo, preselect : true, cancellationToken : cancellationToken).ConfigureAwait(false);

                return(regularItems.Concat(preselectedItems));
            }
        }
        public async Task<CompletionItemGroup> GetGroupAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken = default(CancellationToken))
        {
            var builder = await this.GetBuilderAsync(document, position, triggerInfo, cancellationToken).ConfigureAwait(false);
            if (builder == null)
            {
                return null;
            }

            return new CompletionItemGroup(
                SpecializedCollections.EmptyEnumerable<CompletionItem>(),
                builder,
                isExclusive: false);
        }
        public async Task <CompletionResult> GetCompletionData(int position, char?triggerChar, bool useSignatureHelp)
        {
            IList <ICompletionDataEx> completionData   = null;
            IOverloadProviderEx       overloadProvider = null;
            bool?isCompletion = null;

            var document = _roslynHost.GetDocument(_documentId);

            if (useSignatureHelp || triggerChar != null)
            {
                var signatureHelpProvider = _roslynHost.GetService <ISignatureHelpProvider>();
                var isSignatureHelp       = useSignatureHelp || signatureHelpProvider.IsTriggerCharacter(triggerChar.Value);
                if (isSignatureHelp)
                {
                    var signatureHelp = await signatureHelpProvider.GetItemsAsync(
                        document,
                        position,
                        new SignatureHelpTriggerInfo(
                            useSignatureHelp
                                ? SignatureHelpTriggerReason.InvokeSignatureHelpCommand
                                : SignatureHelpTriggerReason.TypeCharCommand, triggerChar))
                                        .ConfigureAwait(false);

                    if (signatureHelp != null)
                    {
                        overloadProvider = new RoslynOverloadProvider(signatureHelp);
                    }
                }
                else
                {
                    isCompletion = await CompletionService.IsCompletionTriggerCharacterAsync(document, position - 1).ConfigureAwait(false);
                }
            }

            if (overloadProvider == null && isCompletion != false)
            {
                var data = await CompletionService.GetCompletionListAsync(
                    document,
                    position,
                    triggerChar != null
                    ?CompletionTriggerInfo.CreateTypeCharTriggerInfo(triggerChar.Value)
                    : CompletionTriggerInfo.CreateInvokeCompletionTriggerInfo()
                    ).ConfigureAwait(false);

                completionData = data?.Items.Select(item => new RoslynCompletionData(item, _snippetService.SnippetManager)).ToArray <ICompletionDataEx>()
                                 ?? Array.Empty <ICompletionDataEx>();
            }

            return(new CompletionResult(completionData, overloadProvider));
        }
Example #24
0
        protected override async Task <IEnumerable <CompletionItem> > GetItemsWorkerAsync(
            Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            if (syntaxTree.IsInNonUserCode(position, cancellationToken))
            {
                return(null);
            }

            var token = syntaxTree.FindTokenOnLeftOfPosition(position, cancellationToken);

            token = token.GetPreviousTokenIfTouchingWord(position);

            if (token.Kind() != SyntaxKind.OpenParenToken && token.Kind() != SyntaxKind.CommaToken)
            {
                return(null);
            }

            var attributeArgumentList = token.Parent as AttributeArgumentListSyntax;
            var attributeSyntax       = token.Parent.Parent as AttributeSyntax;

            if (attributeSyntax == null || attributeArgumentList == null)
            {
                return(null);
            }

            // We actually want to collect two sets of named parameters to present the user.  The
            // normal named parameters that come from the attribute constructors.  These will be
            // presented like "foo:".  And also the named parameters that come from the writable
            // fields/properties in the attribute.  These will be presented like "bar =".

            var existingNamedParameters = GetExistingNamedParameters(attributeArgumentList, position);

            var workspace     = document.Project.Solution.Workspace;
            var semanticModel = await document.GetSemanticModelForNodeAsync(attributeSyntax, cancellationToken).ConfigureAwait(false);

            var nameColonItems = await GetNameColonItemsAsync(workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false);

            var nameEqualsItems = await GetNameEqualsItemsAsync(workspace, semanticModel, position, token, attributeSyntax, existingNamedParameters, cancellationToken).ConfigureAwait(false);

            // If we're after a name= parameter, then we only want to show name= parameters.
            if (IsAfterNameEqualsArgument(token))
            {
                return(nameEqualsItems);
            }

            return(nameColonItems.Concat(nameEqualsItems));
        }
        private void VerifyItemWithMscorlib45Worker(string xmlString, string expectedItem, string expectedDescription)
        {
            using (var testWorkspace = TestWorkspaceFactory.CreateWorkspace(xmlString))
            {
                var position   = testWorkspace.Documents.Single(d => d.Name == "SourceDocument").CursorPosition.Value;
                var solution   = testWorkspace.CurrentSolution;
                var documentId = testWorkspace.Documents.Single(d => d.Name == "SourceDocument").Id;
                var document   = solution.GetDocument(documentId);

                var triggerInfo    = new CompletionTriggerInfo();
                var completionList = GetCompletionList(document, position, triggerInfo);
                var item           = completionList.Items.FirstOrDefault(i => i.DisplayText == expectedItem);
                Assert.Equal(expectedDescription, item.GetDescriptionAsync().Result.GetFullText());
            }
        }
        private async Task CheckResultsAsync(Document document, int position, string expectedItemOrNull, string expectedDescriptionOrNull, bool usePreviousCharAsTrigger, bool checkForAbsence, Glyph?glyph)
        {
            var code = (await document.GetTextAsync()).ToString();

            CompletionTriggerInfo triggerInfo = new CompletionTriggerInfo();

            if (usePreviousCharAsTrigger)
            {
                triggerInfo = CompletionTriggerInfo.CreateTypeCharTriggerInfo(triggerCharacter: code.ElementAt(position - 1));
            }

            var completionList = await GetCompletionListAsync(document, position, triggerInfo);

            var items = completionList == null ? default(ImmutableArray <CompletionItem>) : completionList.Items;

            if (checkForAbsence)
            {
                if (items == null)
                {
                    return;
                }

                if (expectedItemOrNull == null)
                {
                    Assert.Empty(items);
                }
                else
                {
                    AssertEx.None(
                        items,
                        c => CompareItems(c.DisplayText, expectedItemOrNull) &&
                        (expectedDescriptionOrNull != null ? c.GetDescriptionAsync().Result.GetFullText() == expectedDescriptionOrNull : true));
                }
            }
            else
            {
                if (expectedItemOrNull == null)
                {
                    Assert.NotEmpty(items);
                }
                else
                {
                    AssertEx.Any(items, c => CompareItems(c.DisplayText, expectedItemOrNull) &&
                                 (expectedDescriptionOrNull != null ? c.GetDescriptionAsync().Result.GetFullText() == expectedDescriptionOrNull : true) &&
                                 (glyph.HasValue ? c.Glyph == glyph.Value : true));
                }
            }
        }
        private void CheckResults(Document document, int position, string expectedItemOrNull, string expectedDescriptionOrNull, bool usePreviousCharAsTrigger, bool checkForAbsence, Glyph?glyph)
        {
            var code = document.GetTextAsync().Result.ToString();

            CompletionTriggerInfo completionTriggerInfo = new CompletionTriggerInfo();

            if (usePreviousCharAsTrigger)
            {
                completionTriggerInfo = CompletionTriggerInfo.CreateTypeCharTriggerInfo(triggerCharacter: code.ElementAt(position - 1));
            }

            var group       = CompletionProvider.GetGroupAsync(document, position, completionTriggerInfo).Result;
            var completions = group == null ? null : group.Items;

            if (checkForAbsence)
            {
                if (completions == null)
                {
                    return;
                }

                if (expectedItemOrNull == null)
                {
                    Assert.Empty(completions);
                }
                else
                {
                    AssertEx.None(
                        completions,
                        c => CompareItems(c.DisplayText, expectedItemOrNull) &&
                        (expectedDescriptionOrNull != null ? c.GetDescriptionAsync().Result.GetFullText() == expectedDescriptionOrNull : true));
                }
            }
            else
            {
                if (expectedItemOrNull == null)
                {
                    Assert.NotEmpty(completions);
                }
                else
                {
                    AssertEx.Any(completions, c => CompareItems(c.DisplayText, expectedItemOrNull) &&
                                 (expectedDescriptionOrNull != null ? c.GetDescriptionAsync().Result.GetFullText() == expectedDescriptionOrNull : true) &&
                                 (glyph.HasValue ? c.Glyph == glyph.Value : true));
                }
            }
        }
Example #28
0
        private async Task VerifyExclusiveAsync(string markup, bool exclusive)
        {
            using (var workspace = await CSharpWorkspaceFactory.CreateWorkspaceFromFileAsync(markup))
            {
                var hostDocument = workspace.Documents.Single();
                var position     = hostDocument.CursorPosition.Value;
                var document     = workspace.CurrentSolution.GetDocument(hostDocument.Id);
                var triggerInfo  = CompletionTriggerInfo.CreateTypeCharTriggerInfo('a');

                var completionList = await GetCompletionListAsync(document, position, triggerInfo);

                if (completionList != null)
                {
                    Assert.True(exclusive == completionList.IsExclusive, "group.IsExclusive == " + completionList.IsExclusive);
                }
            }
        }
            public void ComputeModel(
                ICompletionService completionService,
                CompletionTriggerInfo triggerInfo,
                IEnumerable <CompletionListProvider> completionProviders,
                bool isDebugger)
            {
                AssertIsForeground();

                // If we've already computed a model then we can just ignore this request and not
                // generate any tasks.
                if (this.Computation.InitialUnfilteredModel != null)
                {
                    return;
                }

                new ModelComputer(this, completionService, triggerInfo, completionProviders, isDebugger).Do();
            }
        private IEnumerable <CompletionItem> GetItems(SourceText text, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var line     = text.Lines.GetLineFromPosition(position);
            var lineText = text.ToString(TextSpan.FromBounds(line.Start, position));
            var match    = s_directiveRegex.Match(lineText);

            if (!match.Success)
            {
                return(null);
            }

            var quotedPathGroup = match.Groups[1];
            var quotedPath      = quotedPathGroup.Value;
            var endsWithQuote   = PathCompletionUtilities.EndsWithQuote(quotedPath);

            if (endsWithQuote && (position >= line.Start + match.Length))
            {
                return(null);
            }

            var buffer   = text.Container.GetTextBuffer();
            var snapshot = text.FindCorrespondingEditorTextSnapshot();

            if (snapshot == null)
            {
                return(null);
            }

            var fileSystem = PathCompletionUtilities.GetCurrentWorkingDirectoryDiscoveryService(snapshot);

            var searchPaths = ImmutableArray.Create <string>(fileSystem.CurrentDirectory);

            var helper = new FileSystemCompletionHelper(
                this,
                GetTextChangeSpan(text, position, quotedPathGroup),
                fileSystem,
                Glyph.OpenFolder,
                Glyph.CSharpFile,
                searchPaths: searchPaths,
                allowableExtensions: new[] { ".csx" });

            var pathThroughLastSlash = this.GetPathThroughLastSlash(text, position, quotedPathGroup);

            return(helper.GetItems(pathThroughLastSlash, documentPath: null));
        }
        private void CheckResults(Document document, int position, bool isBuilder)
        {
            var triggerInfo    = CompletionTriggerInfo.CreateTypeCharTriggerInfo('a');
            var completionList = GetCompletionList(document, position, triggerInfo);

            if (isBuilder)
            {
                Assert.NotNull(completionList);
                Assert.NotNull(completionList.Builder);
            }
            else
            {
                if (completionList != null)
                {
                    Assert.True(completionList.Builder == null, "group.Builder == " + (completionList.Builder != null ? completionList.Builder.DisplayText : "null"));
                }
            }
        }
Example #32
0
        bool ShouldTriggerCompletion(
            WordAtPosition word,
            CodeCompletionContext completionContext,
            CompletionTriggerInfo triggerInfo)
        {
            switch (triggerInfo.CompletionTriggerReason)
            {
            case CompletionTriggerReason.CharTyped:
                return(ShouldTriggerCompletionOnCharTyped(word, completionContext, triggerInfo));

            case CompletionTriggerReason.BackspaceOrDeleteCommand:
                return(ShouldTriggerCompletionAtPosition(word, completionContext));

            default:
                // Always trigger when Ctrl+Space typed.
                return(true);
            }
        }
            private bool MatchesFilterText(
                CompletionItem item,
                string filterText,
                IList <ICompletionRules> completionRulesList,
                CompletionTriggerInfo triggerInfo,
                CompletionFilterReason reason)
            {
                foreach (var completionRule in completionRulesList)
                {
                    var result = completionRule.MatchesFilterText(item, filterText, triggerInfo, reason);
                    if (result.HasValue)
                    {
                        return(result.Value);
                    }
                }

                return(false);
            }
        private async Task<IEnumerable<CompletionItem>> GetItemsAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            if (document == null)
            {
                return null;
            }

            // If we were triggered by typign a character, then do a semantic check to make sure
            // we're still applicable.  If not, then return immediately.
            if (triggerInfo.TriggerReason == CompletionTriggerReason.TypeCharCommand)
            {
                var isSemanticTriggerCharacter = await IsSemanticTriggerCharacterAsync(document, position - 1, cancellationToken).ConfigureAwait(false);
                if (!isSemanticTriggerCharacter)
                {
                    return null;
                }
            }

            return await GetItemsWorkerAsync(document, position, triggerInfo, cancellationToken).ConfigureAwait(false);
        }
        protected override async Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var workspace = document.Project.Solution.Workspace;
            var semanticModel = await document.GetSemanticModelForSpanAsync(new TextSpan(position, 0), cancellationToken).ConfigureAwait(false);
            var typeAndLocation = GetInitializedType(document, semanticModel, position, cancellationToken);

            if (typeAndLocation == null)
            {
                return null;
            }

            var initializedType = typeAndLocation.Item1 as INamedTypeSymbol;
            var initializerLocation = typeAndLocation.Item2;
            if (initializedType == null)
            {
                return null;
            }

            // Find the members that can be initialized. If we have a NamedTypeSymbol, also get the overridden members.
            IEnumerable<ISymbol> members = semanticModel.LookupSymbols(position, initializedType);
            members = members.Where(m => IsInitializable(m, initializedType) &&
                                         m.CanBeReferencedByName &&
                                         IsLegalFieldOrProperty(m) &&
                                         !m.IsImplicitlyDeclared);

            // Filter out those members that have already been typed
            var alreadyTypedMembers = GetInitializedMembers(semanticModel.SyntaxTree, position, cancellationToken);
            var uninitializedMembers = members.Where(m => !alreadyTypedMembers.Contains(m.Name));

            uninitializedMembers = uninitializedMembers.Where(m => m.IsEditorBrowsable(document.ShouldHideAdvancedMembers(), semanticModel.Compilation));

            var text = await semanticModel.SyntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false);
            var changes = GetTextChangeSpan(text, position);

            // Return the members
            return uninitializedMembers.Select(
                m => CreateItem(workspace, m.Name, changes,
                    CommonCompletionUtilities.CreateDescriptionFactory(workspace, semanticModel, initializerLocation.SourceSpan.Start, m),
                    m.GetGlyph()));
        }
 protected OptionSet GetOptions(Document document, CompletionTriggerInfo triggerInfo, AbstractSyntaxContext context)
 {
     var optionService = context.GetWorkspaceService<IOptionService>();
     var filterOutOfScopeLocals = !triggerInfo.IsDebugger;
     var hideAdvancedMembers = document.ShouldHideAdvancedMembers();
     var options = optionService
         .GetOptions()
         .WithChangedOption(RecommendationOptions.FilterOutOfScopeLocals, context.SemanticModel.Language, filterOutOfScopeLocals)
         .WithChangedOption(RecommendationOptions.HideAdvancedMembers, context.SemanticModel.Language, hideAdvancedMembers);
     return options;
 }
        private async Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync(Document document, int position, CompletionTriggerInfo triggerInfo, bool preselect, CancellationToken cancellationToken)
        {
            var relatedDocumentIds = document.GetLinkedDocumentIds();
            var relatedDocuments = relatedDocumentIds.Concat(document.Id).Select(document.Project.Solution.GetDocument);
            lock (s_cacheGate)
            {
                // Invalidate the cache if it's for a different position or a different set of Documents.
                // It's fairly likely that we'll only have to check the first document, unless someone
                // specially constructed a Solution with mismatched linked files.
                if (s_cachedPosition != position ||
                    !relatedDocuments.All(s_cachedDocuments.ContainsKey))
                {
                    s_cachedPosition = position;
                    s_cachedDocuments.Clear();
                    foreach (var related in relatedDocuments)
                    {
                        s_cachedDocuments.Add(related, null);
                    }
                }
            }

            var context = await GetOrCreateContext(document, position, cancellationToken).ConfigureAwait(false);
            var options = GetOptions(document, triggerInfo, context);

            if (!relatedDocumentIds.Any())
            {
                IEnumerable<ISymbol> itemsForCurrentDocument = await GetSymbolsWorker(position, preselect, context, options, cancellationToken).ConfigureAwait(false);

                itemsForCurrentDocument = itemsForCurrentDocument ?? SpecializedCollections.EmptyEnumerable<ISymbol>();
                return await CreateItemsAsync(position, itemsForCurrentDocument, context, null, null, preselect, cancellationToken).ConfigureAwait(false);
            }

            var contextAndSymbolLists = await GetPerContextSymbols(document, position, options, relatedDocumentIds.Concat(document.Id), preselect, cancellationToken).ConfigureAwait(false);

            Dictionary<ISymbol, AbstractSyntaxContext> orignatingContextMap = null;
            var unionedSymbolsList = UnionSymbols(contextAndSymbolLists, out orignatingContextMap);
            var missingSymbolsMap = FindSymbolsMissingInLinkedContexts(unionedSymbolsList, contextAndSymbolLists);
            var totalProjects = contextAndSymbolLists.Select(t => t.Item1.ProjectId).ToList();

            var textChangeSpan = await GetTextChangeSpanAsync(position, context, cancellationToken).ConfigureAwait(false);

            return CreateItems(position, unionedSymbolsList, textChangeSpan, orignatingContextMap, missingSymbolsMap, totalProjects, preselect: preselect, cancellationToken: cancellationToken);
        }
 protected override async Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync(
     Document document, int position, CompletionTriggerInfo triggerInfo,
     CancellationToken cancellationToken)
 {
     using (Logger.LogBlock(FunctionId.Completion_SymbolCompletionProvider_GetItemsWorker, cancellationToken))
     {
         var regularItems = await GetItemsWorkerAsync(document, position, triggerInfo, preselect: false, cancellationToken: cancellationToken).ConfigureAwait(false);
         var preselectedItems = await GetItemsWorkerAsync(document, position, triggerInfo, preselect: true, cancellationToken: cancellationToken).ConfigureAwait(false);
         return regularItems.Concat(preselectedItems);
     }
 }
        private async Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync(Document document, int position, CompletionTriggerInfo triggerInfo, bool preselect, CancellationToken cancellationToken)
        {
            var context = await CreateContext(document, position, cancellationToken).ConfigureAwait(false);
            var options = GetOptions(document, triggerInfo, context);
            var relatedDocuments = document.GetLinkedDocumentIds();

            if (!relatedDocuments.Any())
            {
                IEnumerable<ISymbol> itemsForCurrentDocument = await GetSymbolsWorker(position, preselect, context, options, cancellationToken).ConfigureAwait(false);

                itemsForCurrentDocument = itemsForCurrentDocument ?? SpecializedCollections.EmptyEnumerable<ISymbol>();
                return await CreateItemsAsync(position, itemsForCurrentDocument, context, null, null, preselect, cancellationToken).ConfigureAwait(false);
            }

            var contextAndSymbolLists = await GetPerContextSymbols(document, position, options, relatedDocuments.Concat(document.Id), preselect, cancellationToken).ConfigureAwait(false);

            Dictionary<ISymbol, AbstractSyntaxContext> orignatingContextMap = null;
            var unionedSymbolsList = UnionSymbols(contextAndSymbolLists, out orignatingContextMap);
            var missingSymbolsMap = FindSymbolsMissingInLinkedContexts(unionedSymbolsList, contextAndSymbolLists);
            var totalProjects = contextAndSymbolLists.Select(t => t.Item1.ProjectId).ToList();

            var textChangeSpan = await GetTextChangeSpanAsync(position, context, cancellationToken).ConfigureAwait(false);

            return CreateItems(position, unionedSymbolsList, textChangeSpan, orignatingContextMap, missingSymbolsMap, totalProjects, preselect: preselect, cancellationToken: cancellationToken);
        }
 protected virtual Task<CompletionItem> GetBuilderAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken)
 {
     return SpecializedTasks.Default<CompletionItem>();
 }
 protected abstract Task<IEnumerable<CompletionItem>> GetItemsWorkerAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken);
 protected abstract Task<CompletionItem> GetBuilderAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken);
 /// <summary>
 /// Returns a CompletionItemGroup for the specified position in the text.
 /// </summary>
 public abstract CompletionList GetCompletionList(SourceText text, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken = default(CancellationToken));
 protected virtual Task<bool> IsExclusiveAsync(Document document, int position, CompletionTriggerInfo triggerInfo, CancellationToken cancellationToken)
 {
     return SpecializedTasks.False;
 }