public override async Task <CompletionChange> GetChangeAsync(LogicalDocument document, CompletionItem item, char?commitKey = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var change = (await GetTextChangeAsync(document, item, commitKey, cancellationToken).ConfigureAwait(false))
                         ?? new TextChange(item.Span, item.DisplayText);

            return(CompletionChange.Create(change));
        }
        private static ImmutableArray <DefinitionItem> GetIncludeDefinitionItem(LogicalDocument document, SyntaxToken syntaxToken)
        {
            var includeDirective = (IncludeDirectiveTriviaSyntax)syntaxToken.Parent;

            var syntaxTree = document.GetSyntaxTreeSynchronously(CancellationToken.None);

            var workspace = document.Workspace;

            var includeFileSystem = workspace.Services.GetRequiredService <IWorkspaceIncludeFileSystem>();

            var parseOptions        = (HlslParseOptions)syntaxTree.Options;
            var includeFileResolver = new IncludeFileResolver(includeFileSystem, parseOptions);

            var currentFile = ((SyntaxTree)syntaxTree).File;

            var include = includeFileResolver.OpenInclude(includeDirective.TrimmedFilename, currentFile);

            if (include == null)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var fileSpan = new CodeAnalysis.Text.SourceFileSpan(include, new CodeAnalysis.Text.TextSpan(0, 0));

            var definitionItem = DefinitionItem.Create(
                ImmutableArray <string> .Empty,
                ImmutableArray <TaggedText> .Empty,
                new DocumentSpan(document, fileSpan),
                ImmutableArray <TaggedText> .Empty);

            return(ImmutableArray.Create(definitionItem));
        }
        public async Task <ImmutableArray <DefinitionItem> > FindDefinitionsAsync(LogicalDocument document, int position, CancellationToken cancellationToken)
        {
            var syntacticDefinitions = await GetSyntacticDefinitionsAsync(document, position, cancellationToken);

            if (!syntacticDefinitions.IsEmpty)
            {
                return(syntacticDefinitions);
            }

            // First try to compute the referenced symbol and attempt to go to definition for the symbol.
            var symbol = await FindSymbolAsync(document, position, cancellationToken);

            if (symbol == null)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var definition = await SymbolFinder.FindSourceDefinitionAsync(symbol, cancellationToken);

            cancellationToken.ThrowIfCancellationRequested();

            symbol = definition ?? symbol;

            if (symbol.Locations.IsEmpty)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var workspace = document.Workspace;
            var options   = workspace.Options;

            return(ImmutableArray.Create(symbol.ToDefinitionItem(workspace)));
        }
예제 #4
0
        public static Range ToRange(LogicalDocument document, TextSpan textSpan)
        {
            // Map textSpan to parent document.
            textSpan = new TextSpan(textSpan.Start + document.SpanInParentRootFile.Start, textSpan.Length);

            return(ToRange(document.Parent.SourceText, textSpan));
        }
예제 #5
0
 /// <summary>
 /// Gets the description of the item.
 /// </summary>
 /// <param name="document">The document that completion is occurring within.</param>
 /// <param name="item">The item to get the description for.</param>
 /// <param name="cancellationToken"></param>
 public virtual Task <CompletionDescription> GetDescriptionAsync(
     LogicalDocument document,
     CompletionItem item,
     CancellationToken cancellationToken = default(CancellationToken))
 {
     return(Task.FromResult(CompletionDescription.Empty));
 }
예제 #6
0
 /// <summary>
 /// Gets the completions available at the caret position.
 /// </summary>
 /// <param name="document">The document that completion is occuring within.</param>
 /// <param name="caretPosition">The position of the caret after the triggering action.</param>
 /// <param name="trigger">The triggering action.</param>
 /// <param name="roles">Optional set of roles associated with the editor state.</param>
 /// <param name="options">Optional options that override the default options.</param>
 /// <param name="cancellationToken"></param>
 public abstract Task <CompletionList> GetCompletionsAsync(
     LogicalDocument document,
     int caretPosition,
     CompletionTrigger trigger       = default(CompletionTrigger),
     ImmutableHashSet <string> roles = null,
     OptionSet options = null,
     CancellationToken cancellationToken = default(CancellationToken));
예제 #7
0
        public async Task <SignatureHelpItems> GetItemsAsync(
            LogicalDocument document, int position, SignatureHelpTriggerInfo triggerInfo, CancellationToken cancellationToken)
        {
            var itemsForCurrentDocument = await GetItemsWorkerAsync(document, position, triggerInfo, cancellationToken).ConfigureAwait(false);

            return(itemsForCurrentDocument);
        }
예제 #8
0
 public MappedDiagnostic(Diagnostic diagnostic, DiagnosticSource source, SourceFileSpan fileSpan, LogicalDocument logicalDocument)
 {
     Diagnostic      = diagnostic;
     FileSpan        = fileSpan;
     Source          = source;
     LogicalDocument = logicalDocument;
 }
 public IQuickInfoProviderCoordinator CreateCoordinator(LogicalDocument document)
 {
     return(new QuickInfoProviderCoordinator(_providers
                                             .Where(x => x.Metadata.Language == document.Language)
                                             .Select(x => x.Value)
                                             .ToList()));
 }
        protected override async Task <QuickInfoContent> BuildContentAsync(LogicalDocument document, ISyntaxToken token, CancellationToken cancellationToken)
        {
            var macroDefinitionNode = token.Parent as DefineDirectiveTriviaSyntax;

            if (macroDefinitionNode != null && macroDefinitionNode.MacroName == token)
            {
                return(new QuickInfoDisplayContent(
                           LanguageNames.Hlsl,
                           Glyph.Macro,
                           ImmutableArray.Create(new TaggedText(TextTags.Text, $"(macro definition) {macroDefinitionNode}")),
                           ImmutableArray <TaggedText> .Empty));
            }

            var syntaxToken    = (SyntaxToken)token;
            var macroReference = syntaxToken.MacroReference;

            if (macroReference != null && macroReference.SourceRange == token.SourceRange)
            {
                return(new QuickInfoDisplayContent(
                           LanguageNames.Hlsl,
                           Glyph.Macro,
                           ImmutableArray.Create(new TaggedText(TextTags.Text, $"(macro reference) {macroReference.DefineDirective.ToString(true)}")),
                           ImmutableArray <TaggedText> .Empty));
            }

            return(null);
        }
예제 #11
0
        public async Task <QuickInfoItem> GetItemAsync(
            LogicalDocument document,
            int position,
            CancellationToken cancellationToken)
        {
            var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var sourceLocation = tree.MapRootFilePosition(position);
            var token          = await tree.GetTouchingTokenAsync(sourceLocation, cancellationToken, findInsideTrivia : true).ConfigureAwait(false);

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

            var state = await GetQuickInfoItemAsync(document, tree, token, sourceLocation, cancellationToken).ConfigureAwait(false);

            if (state != null)
            {
                return(state);
            }

            if (ShouldCheckPreviousToken(token))
            {
                var previousToken = token.GetPreviousToken();

                if ((state = await GetQuickInfoItemAsync(document, tree, previousToken, sourceLocation, cancellationToken).ConfigureAwait(false)) != null)
                {
                    return(state);
                }
            }

            return(null);
        }
 protected virtual Task <CompletionDescription> GetDescriptionWorkerAsync(
     LogicalDocument document, CompletionItem item, CancellationToken cancellationToken)
 {
     return(CommonCompletionItem.HasDescription(item)
         ? Task.FromResult(CommonCompletionItem.GetDescription(item))
         : Task.FromResult(CompletionDescription.Empty));
 }
예제 #13
0
 /// <summary>
 /// Gets the change to be applied when the item is committed.
 /// </summary>
 /// <param name="document">The document that completion is occurring within.</param>
 /// <param name="item">The item to get the change for.</param>
 /// <param name="commitCharacter">The typed character that caused the item to be committed.
 /// This character may be used as part of the change.
 /// This value is null when the commit was caused by the [TAB] or [ENTER] keys.</param>
 /// <param name="cancellationToken"></param>
 public virtual Task <CompletionChange> GetChangeAsync(
     LogicalDocument document,
     CompletionItem item,
     char?commitCharacter = null,
     CancellationToken cancellationToken = default(CancellationToken))
 {
     return(Task.FromResult(CompletionChange.Create(new TextChange(item.Span, item.DisplayText))));
 }
예제 #14
0
 // Internal for testing purposes only.
 internal async Task <CompletionContext> GetContextAsync(
     CompletionProvider provider,
     LogicalDocument document,
     int position,
     CompletionTrigger triggerInfo,
     OptionSet options,
     CancellationToken cancellationToken)
 {
     return(await GetContextAsync(
                provider, document, position, triggerInfo,
                options, defaultSpan : null, cancellationToken : cancellationToken).ConfigureAwait(false));
 }
        public sealed override async Task <CompletionDescription> GetDescriptionAsync(
            LogicalDocument document, CompletionItem item, CancellationToken cancellationToken)
        {
            // Get the actual description provided by whatever subclass we are.
            // Then, if we would commit text that could be expanded as a snippet,
            // put that information in the description so that the user knows.
            var description = await this.GetDescriptionWorkerAsync(document, item, cancellationToken).ConfigureAwait(false);

            var parts = description.TaggedParts;

            return(description.WithTaggedParts(parts));
        }
예제 #16
0
        public override Task <CompletionDescription> GetDescriptionAsync(LogicalDocument document, CompletionItem item, CancellationToken cancellationToken = default(CancellationToken))
        {
            var provider = GetProvider(item);

            if (provider != null)
            {
                return(provider.GetDescriptionAsync(document, item, cancellationToken));
            }
            else
            {
                return(Task.FromResult(CompletionDescription.Empty));
            }
        }
예제 #17
0
 public SearchResult(
     LogicalDocument document, ISymbol declaredSymbol, string kind,
     NavigateToMatchKind matchKind, bool isCaseSensitive, INavigableItem navigableItem)
 {
     _document       = document;
     _declaredSymbol = declaredSymbol;
     Kind            = kind;
     MatchKind       = matchKind;
     IsCaseSensitive = isCaseSensitive;
     NavigableItem   = navigableItem;
     //SecondarySort = ConstructSecondarySortString(document, declaredSymbolInfo);
     SecondarySort = null;
 }
예제 #18
0
        public async Task <ImmutableArray <BlockSpan> > ProvideBlockStructureAsync(LogicalDocument document, CancellationToken cancellationToken)
        {
            var results          = ImmutableArray.CreateBuilder <BlockSpan>();
            var outliningVisitor = new OutliningVisitor(document.SourceText, results, cancellationToken);

            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            if (syntaxTree != null)
            {
                outliningVisitor.VisitCompilationUnit((CompilationUnitSyntax)syntaxTree.Root);
            }

            return(results.ToImmutable());
        }
예제 #19
0
        public override async Task <CompletionChange> GetChangeAsync(
            LogicalDocument document, CompletionItem item, char?commitKey, CancellationToken cancellationToken)
        {
            var provider = GetProvider(item);

            if (provider != null)
            {
                return(await provider.GetChangeAsync(document, item, commitKey, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                return(CompletionChange.Create(new TextChange(item.Span, item.DisplayText)));
            }
        }
        public async Task <(QuickInfoItem, IQuickInfoProvider)> GetItemAsync(LogicalDocument document, int position, CancellationToken cancellationToken)
        {
            foreach (var provider in _providers)
            {
                var item = await provider.GetItemAsync(document, position, cancellationToken).ConfigureAwait(false);

                if (item != null)
                {
                    return(item, provider);
                }
            }

            return((QuickInfoItem)null, (IQuickInfoProvider)null);
        }
예제 #21
0
 /// <summary>
 /// Creates a <see cref="CompletionContext"/> instance.
 /// </summary>
 public CompletionContext(
     CompletionProvider provider,
     LogicalDocument document,
     int position,
     TextSpan defaultSpan,
     CompletionTrigger trigger,
     OptionSet options,
     CancellationToken cancellationToken)
 {
     this.Provider           = provider ?? throw new ArgumentNullException(nameof(provider));
     this.Document           = document ?? throw new ArgumentNullException(nameof(document));
     this.Position           = position;
     this.CompletionListSpan = defaultSpan;
     this.Trigger            = trigger;
     this.Options            = options ?? throw new ArgumentException(nameof(options));
     this.CancellationToken  = cancellationToken;
     _items = new List <CompletionItem>();
 }
예제 #22
0
        protected override async Task <QuickInfoContent> BuildContentAsync(
            LogicalDocument document,
            ISyntaxToken token,
            CancellationToken cancellationToken)
        {
            var modelAndSymbols = await this.BindTokenAsync(document, token, cancellationToken).ConfigureAwait(false);

            if (modelAndSymbols.Item2.Length == 0)
            {
                return(null);
            }

            return(await CreateContentAsync(document.Workspace,
                                            token,
                                            modelAndSymbols.Item1,
                                            modelAndSymbols.Item2,
                                            cancellationToken : cancellationToken).ConfigureAwait(false));
        }
예제 #23
0
        private async Task <ImmutableArray <CompletionContext> > ComputeNonEmptyCompletionContextsAsync(
            LogicalDocument document, int caretPosition, CompletionTrigger trigger,
            OptionSet options, TextSpan defaultItemSpan,
            ImmutableArray <CompletionProvider> providers,
            CancellationToken cancellationToken)
        {
            var completionContextTasks = new List <Task <CompletionContext> >();

            foreach (var provider in providers)
            {
                completionContextTasks.Add(GetContextAsync(
                                               provider, document, caretPosition, trigger,
                                               options, defaultItemSpan, cancellationToken));
            }

            var completionContexts = await Task.WhenAll(completionContextTasks).ConfigureAwait(false);

            var nonEmptyContexts = completionContexts.Where(HasAnyItems).ToImmutableArray();

            return(nonEmptyContexts);
        }
예제 #24
0
        private async Task <QuickInfoItem> GetQuickInfoItemAsync(
            LogicalDocument document,
            SyntaxTreeBase syntaxTree,
            ISyntaxToken token,
            SourceLocation sourceLocation,
            CancellationToken cancellationToken)
        {
            if (token != default(ISyntaxToken) &&
                token.SourceRange.Contains(sourceLocation))
            {
                var deferredContent = await BuildContentAsync(document, token, cancellationToken).ConfigureAwait(false);

                if (deferredContent != null)
                {
                    var rootSpan = syntaxTree.GetSourceFileSpan(token.SourceRange).Span;
                    return(new QuickInfoItem(rootSpan, deferredContent));
                }
            }

            return(null);
        }
예제 #25
0
        private static CompletionItem ConvertCompletionItem(LogicalDocument document, CompletionRules completionRules, CodeAnalysis.Completion.CompletionItem item)
        {
            var documentation = CommonCompletionItem.HasDescription(item)
                ? CommonCompletionItem.GetDescription(item).Text
                : string.Empty;

            return(new CompletionItem
            {
                Label = item.DisplayText,
                SortText = item.SortText,
                FilterText = item.FilterText,
                Kind = GetKind(item.Glyph),
                TextEdit = new TextEdit
                {
                    NewText = item.DisplayText,
                    Range = Helpers.ToRange(document, item.Span)
                },
                Documentation = documentation,
                CommitCharacters = completionRules.DefaultCommitCharacters.Select(x => x.ToString()).ToArray()
            });
        }
        private static ImmutableArray <DefinitionItem> GetMacroDefinitionItem(LogicalDocument document, CodeAnalysis.Text.SourceLocation sourceLocation, SyntaxToken syntaxToken)
        {
            var nameToken = syntaxToken.MacroReference.NameToken;

            if (!nameToken.SourceRange.ContainsOrTouches(sourceLocation))
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            if (!nameToken.FileSpan.IsInRootFile)
            {
                return(ImmutableArray <DefinitionItem> .Empty);
            }

            var definitionItem = DefinitionItem.Create(
                ImmutableArray <string> .Empty,
                ImmutableArray <TaggedText> .Empty,
                new DocumentSpan(document, syntaxToken.MacroReference.DefineDirective.MacroName.FileSpan),
                ImmutableArray <TaggedText> .Empty);

            return(ImmutableArray.Create(definitionItem));
        }
        private async Task <ISymbol> FindSymbolAsync(LogicalDocument document, int position, CancellationToken cancellationToken)
        {
            if (!document.SupportsSemanticModel)
            {
                return(null);
            }

            var workspace = document.Workspace;

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var semanticInfo = await SymbolFinder.GetSemanticInfoAtPositionAsync(semanticModel, position, workspace, cancellationToken).ConfigureAwait(false);

            // prefer references to declarations.  It's more likely that the user is attempting to
            // go to a definition at some other location, rather than the definition they're on.
            // This can happen when a token is at a location that is both a reference and a definition.
            // For example, on an anonymous type member declaration.
            return(semanticInfo.AliasSymbol ??
                   semanticInfo.ReferencedSymbols.FirstOrDefault() ??
                   semanticInfo.DeclaredSymbol ??
                   semanticInfo.Type);
        }
예제 #28
0
        private static IEnumerable <INavigateToSearchResult> ConvertResult(
            ISymbol declaredSymbol, LogicalDocument document, SyntaxTreeBase syntaxTree,
            NavigateToMatchKind matchKind)
        {
            var isCaseSensitive = false;
            var kind            = GetItemKind(declaredSymbol.Kind);

            foreach (var location in declaredSymbol.Locations)
            {
                var sourceFileSpan = syntaxTree.GetSourceFileSpan(location);

                if (sourceFileSpan.IsInRootFile)
                {
                    var navigableItem = NavigableItemFactory.GetItemFromDeclaredSymbol(
                        declaredSymbol, document, sourceFileSpan);

                    yield return(new SearchResult(
                                     document, declaredSymbol, kind, matchKind,
                                     isCaseSensitive, navigableItem));
                }
            }
        }
예제 #29
0
        private async Task <ValueTuple <SemanticModelBase, ImmutableArray <ISymbol> > > BindTokenAsync(
            LogicalDocument document,
            ISyntaxToken token,
            CancellationToken cancellationToken)
        {
            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (semanticModel != null)
            {
                var symbols = semanticModel.GetSemanticInfo(token, document.Workspace, cancellationToken)
                              .GetSymbols(includeType: true);

                symbols = symbols.Distinct().ToImmutableArray();

                if (symbols.Any())
                {
                    return(ValueTuple.Create(semanticModel, symbols));
                }
            }

            return(ValueTuple.Create(semanticModel, ImmutableArray <ISymbol> .Empty));
        }
예제 #30
0
        private async Task <CompletionContext> GetContextAsync(
            CompletionProvider provider,
            LogicalDocument document,
            int position,
            CompletionTrigger triggerInfo,
            OptionSet options,
            TextSpan?defaultSpan,
            CancellationToken cancellationToken)
        {
            options = options ?? document.Workspace.Options;

            if (defaultSpan == null)
            {
                var text = document.SourceText;
                defaultSpan = this.GetDefaultCompletionListSpan(text, position);
            }

            var context = new CompletionContext(provider, document, position, defaultSpan.Value, triggerInfo, options, cancellationToken);
            await provider.ProvideCompletionsAsync(context).ConfigureAwait(false);

            return(context);
        }