public Task<MetadataAsSourceFile> GenerateSourceAsync(ISymbol symbol, Project project = null)
            {
                project = project ?? this.DefaultProject;

                // Generate and hold onto the result so it can be disposed of with this context
                return _metadataAsSourceService.GetGeneratedFileAsync(project, symbol);
            }
            public Task <MetadataAsSourceFile> GenerateSourceAsync(ISymbol symbol, Project project = null, bool allowDecompilation = false)
            {
                project = project ?? this.DefaultProject;

                // Generate and hold onto the result so it can be disposed of with this context
                return(_metadataAsSourceService.GetGeneratedFileAsync(project, symbol, allowDecompilation));
            }
Exemplo n.º 3
0
            public Task <MetadataAsSourceFile> GenerateSourceAsync(ISymbol symbol, Project?project = null, bool signaturesOnly = true)
            {
                project ??= this.DefaultProject;
                Contract.ThrowIfNull(symbol);

                // Generate and hold onto the result so it can be disposed of with this context
                return(_metadataAsSourceService.GetGeneratedFileAsync(project, symbol, signaturesOnly, MetadataAsSourceOptions.GetDefault(project.LanguageServices)));
            }
        protected async Task <LSP.Location[]> GetDefinitionAsync(Solution solution, LSP.TextDocumentPositionParams request, bool typeOnly, CancellationToken cancellationToken)
        {
            var locations = ArrayBuilder <LSP.Location> .GetInstance();

            var document = solution.GetDocumentFromURI(request.TextDocument.Uri);

            if (document == null)
            {
                return(locations.ToArrayAndFree());
            }

            var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            var definitionService = document.Project.LanguageServices.GetService <IGoToDefinitionService>();
            var definitions       = await definitionService.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false);

            if (definitions != null && definitions.Count() > 0)
            {
                foreach (var definition in definitions)
                {
                    if (!ShouldInclude(definition, typeOnly))
                    {
                        continue;
                    }

                    var definitionText = await definition.Document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    locations.Add(new LSP.Location
                    {
                        Uri   = definition.Document.GetURI(),
                        Range = ProtocolConversions.TextSpanToRange(definition.SourceSpan, definitionText),
                    });
                }
            }
            else if (document.SupportsSemanticModel && _metadataAsSourceFileService != null)
            {
                // No definition found - see if we can get metadata as source but that's only applicable for C#\VB.
                var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false);

                if (symbol != null && symbol.Locations != null && !symbol.Locations.IsEmpty && symbol.Locations.First().IsInMetadata)
                {
                    if (!typeOnly || symbol is ITypeSymbol)
                    {
                        var declarationFile = await _metadataAsSourceFileService.GetGeneratedFileAsync(document.Project, symbol, false, cancellationToken).ConfigureAwait(false);

                        var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span;
                        locations.Add(new LSP.Location
                        {
                            Uri   = new Uri(declarationFile.FilePath),
                            Range = ProtocolConversions.LinePositionToRange(linePosSpan),
                        });
                    }
                }
            }

            return(locations.ToArrayAndFree());
        protected async Task <LSP.Location[]?> GetDefinitionAsync(LSP.TextDocumentPositionParams request, bool typeOnly, RequestContext context, CancellationToken cancellationToken)
        {
            var document = context.Document;

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

            var locations = ArrayBuilder <LSP.Location> .GetInstance();

            var position = await document.GetPositionFromLinePositionAsync(ProtocolConversions.PositionToLinePosition(request.Position), cancellationToken).ConfigureAwait(false);

            var findDefinitionService = document.GetRequiredLanguageService <IFindDefinitionService>();

            var definitions = await findDefinitionService.FindDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false);

            if (definitions.Any())
            {
                foreach (var definition in definitions)
                {
                    if (!ShouldInclude(definition, typeOnly))
                    {
                        continue;
                    }

                    var location = await ProtocolConversions.TextSpanToLocationAsync(
                        definition.Document, definition.SourceSpan, definition.IsStale, cancellationToken).ConfigureAwait(false);

                    locations.AddIfNotNull(location);
                }
            }
            else if (document.SupportsSemanticModel && _metadataAsSourceFileService != null)
            {
                // No definition found - see if we can get metadata as source but that's only applicable for C#\VB.
                var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false);

                if (symbol != null && _metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol))
                {
                    if (!typeOnly || symbol is ITypeSymbol)
                    {
                        var options         = _globalOptions.GetMetadataAsSourceOptions(document.Project.LanguageServices);
                        var declarationFile = await _metadataAsSourceFileService.GetGeneratedFileAsync(document.Project, symbol, signaturesOnly : false, options, cancellationToken).ConfigureAwait(false);

                        var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span;
                        locations.Add(new LSP.Location
                        {
                            Uri   = new Uri(declarationFile.FilePath),
                            Range = ProtocolConversions.LinePositionToRange(linePosSpan),
                        });
                    }
                }
            }

            return(locations.ToArrayAndFree());
        private async Task <INavigableLocation?> GetNavigableLocationForMetadataAsync(
            Project project, ISymbol symbol, CancellationToken cancellationToken)
        {
            var masOptions = _globalOptions.GetMetadataAsSourceOptions();

            var result = await _metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, signaturesOnly : false, masOptions, cancellationToken).ConfigureAwait(false);

            return(new NavigableLocation(async(options, cancellationToken) =>
            {
                await this.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

                var vsRunningDocumentTable4 = _serviceProvider.GetServiceOnMainThread <SVsRunningDocumentTable, IVsRunningDocumentTable4>();
                var fileAlreadyOpen = vsRunningDocumentTable4.IsMonikerValid(result.FilePath);

                var openDocumentService = _serviceProvider.GetServiceOnMainThread <SVsUIShellOpenDocument, IVsUIShellOpenDocument>();
                openDocumentService.OpenDocumentViaProject(result.FilePath, VSConstants.LOGVIEWID.TextView_guid, out _, out _, out _, out var windowFrame);

                var documentCookie = vsRunningDocumentTable4.GetDocumentCookie(result.FilePath);

                var vsTextBuffer = (IVsTextBuffer)vsRunningDocumentTable4.GetDocumentData(documentCookie);

                // Set the buffer to read only, just in case the file isn't
                ErrorHandler.ThrowOnFailure(vsTextBuffer.GetStateFlags(out var flags));
                flags |= (int)BUFFERSTATEFLAGS.BSF_USER_READONLY;
                ErrorHandler.ThrowOnFailure(vsTextBuffer.SetStateFlags(flags));

                var textBuffer = _editorAdaptersFactory.GetDataBuffer(vsTextBuffer);

                if (!fileAlreadyOpen)
                {
                    ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_IsProvisional, true));
                    ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideCaption, result.DocumentTitle));
                    ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideToolTip, result.DocumentTooltip));
                }

                windowFrame.Show();

                var openedDocument = textBuffer?.AsTextContainer().GetRelatedDocuments().FirstOrDefault();
                if (openedDocument != null)
                {
                    var editorWorkspace = openedDocument.Project.Solution.Workspace;
                    var navigationService = editorWorkspace.Services.GetRequiredService <IDocumentNavigationService>();

                    await navigationService.TryNavigateToSpanAsync(
                        this.ThreadingContext,
                        editorWorkspace,
                        openedDocument.Id,
                        result.IdentifierLocation.SourceSpan,
                        options with {
                        PreferProvisionalTab = true
                    },
                        cancellationToken).ConfigureAwait(false);
                }
Exemplo n.º 7
0
            // Local functions
            static async Task <LSP.Location?> ComputeLocationAsync(
                Document document,
                int position,
                DocumentSpan documentSpan,
                IMetadataAsSourceFileService metadataAsSourceFileService,
                CancellationToken cancellationToken)
            {
                if (documentSpan != default)
                {
                    // We do have a document span, so compute location normally.
                    return(await ProtocolConversions.DocumentSpanToLocationAsync(documentSpan, cancellationToken).ConfigureAwait(false));
                }

                // If we have no document span, our location may be in metadata or may be a namespace.
                var symbol = await SymbolFinder.FindSymbolAtPositionAsync(document, position, cancellationToken).ConfigureAwait(false);

                if (symbol == null || symbol.Locations.IsEmpty || symbol.Kind == SymbolKind.Namespace)
                {
                    // Either:
                    // (1) We couldn't find the location in metadata and it's not in any of our known documents.
                    // (2) The symbol is a namespace (and therefore has no location).
                    return(null);
                }

                var declarationFile = await metadataAsSourceFileService.GetGeneratedFileAsync(
                    document.Project, symbol, allowDecompilation : false, cancellationToken).ConfigureAwait(false);

                var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span;

                if (string.IsNullOrEmpty(declarationFile.FilePath))
                {
                    return(null);
                }

                try
                {
                    return(new LSP.Location
                    {
                        Uri = ProtocolConversions.GetUriFromFilePath(declarationFile.FilePath),
                        Range = ProtocolConversions.LinePositionToRange(linePosSpan),
                    });
                }
                catch (UriFormatException e) when(FatalError.ReportAndCatch(e))
                {
                    // We might reach this point if the file path is formatted incorrectly.
                    return(null);
                }
            }
Exemplo n.º 8
0
        private static async Task <LSP.Location[]> GetSymbolDefinitionLocationsAsync(XamlSymbolDefinition symbolDefinition, RequestContext context, IMetadataAsSourceFileService metadataAsSourceFileService, CancellationToken cancellationToken)
        {
            Contract.ThrowIfNull(symbolDefinition.Symbol);

            using var _ = ArrayBuilder <LSP.Location> .GetInstance(out var locations);

            var symbol = symbolDefinition.Symbol;

            var items = NavigableItemFactory.GetItemsFromPreferredSourceLocations(context.Solution, symbol, displayTaggedParts: null, cancellationToken);

            if (items.Any())
            {
                foreach (var item in items)
                {
                    var location = await ProtocolConversions.TextSpanToLocationAsync(
                        item.Document, item.SourceSpan, item.IsStale, cancellationToken).ConfigureAwait(false);

                    locations.AddIfNotNull(location);
                }
            }
            else
            {
                var metadataLocation = symbol.Locations.Where(loc => loc.IsInMetadata).FirstOrDefault();
                if (metadataLocation != null && metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol))
                {
                    var project = context.Document?.GetCodeProject();
                    if (project != null)
                    {
                        var declarationFile = await metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, allowDecompilation : false, cancellationToken).ConfigureAwait(false);

                        var linePosSpan = declarationFile.IdentifierLocation.GetLineSpan().Span;
                        locations.Add(new LSP.Location
                        {
                            Uri   = new Uri(declarationFile.FilePath),
                            Range = ProtocolConversions.LinePositionToRange(linePosSpan),
                        });
                    }
                }
            }

            return(locations.ToArray());
        }
        public bool TryNavigateToSymbol(ISymbol symbol, Project project, bool usePreviewTab = false)
        {
            if (project == null || symbol == null)
            {
                return(false);
            }

            symbol = symbol.OriginalDefinition;

            // Prefer visible source locations if possible.
            var sourceLocations        = symbol.Locations.Where(loc => loc.IsInSource);
            var visibleSourceLocations = sourceLocations.Where(loc => loc.IsVisibleSourceLocation());
            var sourceLocation         = visibleSourceLocations.Any() ? visibleSourceLocations.First() : sourceLocations.FirstOrDefault();

            if (sourceLocation != null)
            {
                var targetDocument = project.Solution.GetDocument(sourceLocation.SourceTree);
                if (targetDocument != null)
                {
                    var editorWorkspace   = targetDocument.Project.Solution.Workspace;
                    var navigationService = editorWorkspace.Services.GetService <IDocumentNavigationService>();
                    return(navigationService.TryNavigateToSpan(editorWorkspace, targetDocument.Id, sourceLocation.SourceSpan, usePreviewTab));
                }
            }

            // We don't have a source document, so show the Metadata as Source view in a preview tab.

            var metadataLocation = symbol.Locations.Where(loc => loc.IsInMetadata).FirstOrDefault();

            if (metadataLocation == null || !_metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol))
            {
                return(false);
            }

            // Generate new source or retrieve existing source for the symbol in question
            var result = _metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol).WaitAndGetResult(CancellationToken.None);

            var vsRunningDocumentTable4 = GetService <SVsRunningDocumentTable, IVsRunningDocumentTable4>();
            var fileAlreadyOpen         = vsRunningDocumentTable4.IsMonikerValid((string)result.FilePath);

            var openDocumentService = GetService <SVsUIShellOpenDocument, IVsUIShellOpenDocument>();

            IVsUIHierarchy      hierarchy;
            uint                itemId;
            IOleServiceProvider localServiceProvider;
            IVsWindowFrame      windowFrame;

            openDocumentService.OpenDocumentViaProject(result.FilePath, VSConstants.LOGVIEWID.TextView_guid, out localServiceProvider, out hierarchy, out itemId, out windowFrame);

            var documentCookie = vsRunningDocumentTable4.GetDocumentCookie(result.FilePath);

            var vsTextBuffer = (IVsTextBuffer)vsRunningDocumentTable4.GetDocumentData(documentCookie);
            var textBuffer   = _editorAdaptersFactory.GetDataBuffer((IVsTextBuffer)vsTextBuffer);

            if (!fileAlreadyOpen)
            {
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_IsProvisional, true));
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideCaption, result.DocumentTitle));
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideToolTip, result.DocumentTooltip));
            }

            windowFrame.Show();

            var openedDocument = textBuffer.AsTextContainer().GetRelatedDocuments().FirstOrDefault();

            if (openedDocument != null)
            {
                var editorWorkspace   = openedDocument.Project.Solution.Workspace;
                var navigationService = editorWorkspace.Services.GetService <IDocumentNavigationService>();
                return(navigationService.TryNavigateToSpan(editorWorkspace, openedDocument.Id, result.IdentifierLocation.SourceSpan, usePreviewTab: true));
            }

            return(true);
        }
Exemplo n.º 10
0
        public bool TryNavigateToSymbol(ISymbol symbol, Project project, OptionSet?options, CancellationToken cancellationToken)
        {
            if (project == null || symbol == null)
            {
                return(false);
            }

            options ??= project.Solution.Options;
            symbol = symbol.OriginalDefinition;

            // Prefer visible source locations if possible.
            var sourceLocations        = symbol.Locations.Where(loc => loc.IsInSource);
            var visibleSourceLocations = sourceLocations.Where(loc => loc.IsVisibleSourceLocation());
            var sourceLocation         = visibleSourceLocations.FirstOrDefault() ?? sourceLocations.FirstOrDefault();

            if (sourceLocation != null)
            {
                var targetDocument = project.Solution.GetDocument(sourceLocation.SourceTree);
                if (targetDocument != null)
                {
                    var editorWorkspace   = targetDocument.Project.Solution.Workspace;
                    var navigationService = editorWorkspace.Services.GetRequiredService <IDocumentNavigationService>();
                    return(navigationService.TryNavigateToSpan(editorWorkspace, targetDocument.Id, sourceLocation.SourceSpan, options, cancellationToken));
                }
            }

            // We don't have a source document, so show the Metadata as Source view in a preview tab.

            var metadataLocation = symbol.Locations.Where(loc => loc.IsInMetadata).FirstOrDefault();

            if (metadataLocation == null || !_metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol))
            {
                return(false);
            }

            // Should we prefer navigating to the Object Browser over metadata-as-source?
            if (_globalOptions.GetOption(VisualStudioNavigationOptions.NavigateToObjectBrowser, project.Language))
            {
                var libraryService = project.LanguageServices.GetService <ILibraryService>();
                if (libraryService == null)
                {
                    return(false);
                }

                var compilation = project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken);
                var navInfo     = libraryService.NavInfoFactory.CreateForSymbol(symbol, project, compilation);
                if (navInfo == null)
                {
                    navInfo = libraryService.NavInfoFactory.CreateForProject(project);
                }

                if (navInfo != null)
                {
                    var navigationTool = IServiceProviderExtensions.GetService <SVsObjBrowser, IVsNavigationTool>(_serviceProvider);
                    return(navigationTool.NavigateToNavInfo(navInfo) == VSConstants.S_OK);
                }

                // Note: we'll fallback to Metadata-As-Source if we fail to get IVsNavInfo, but that should never happen.
            }

            // Generate new source or retrieve existing source for the symbol in question
            var allowDecompilation = false;

            // Check whether decompilation is supported for the project. We currently only support this for C# projects.
            if (project.LanguageServices.GetService <IDecompiledSourceService>() != null)
            {
                allowDecompilation = project.Solution.Workspace.Options.GetOption(FeatureOnOffOptions.NavigateToDecompiledSources) && !symbol.IsFromSource();
            }

            var result = _metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, allowDecompilation, cancellationToken).WaitAndGetResult(cancellationToken);

            var vsRunningDocumentTable4 = IServiceProviderExtensions.GetService <SVsRunningDocumentTable, IVsRunningDocumentTable4>(_serviceProvider);
            var fileAlreadyOpen         = vsRunningDocumentTable4.IsMonikerValid(result.FilePath);

            var openDocumentService = IServiceProviderExtensions.GetService <SVsUIShellOpenDocument, IVsUIShellOpenDocument>(_serviceProvider);

            openDocumentService.OpenDocumentViaProject(result.FilePath, VSConstants.LOGVIEWID.TextView_guid, out var localServiceProvider, out var hierarchy, out var itemId, out var windowFrame);

            var documentCookie = vsRunningDocumentTable4.GetDocumentCookie(result.FilePath);

            // The cast from dynamic to object doesn't change semantics, but avoids loading the dynamic binder
            // which saves us JIT time in this method.
            var vsTextBuffer = (IVsTextBuffer)(object)vsRunningDocumentTable4.GetDocumentData(documentCookie);
            var textBuffer   = _editorAdaptersFactory.GetDataBuffer(vsTextBuffer);

            if (!fileAlreadyOpen)
            {
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_IsProvisional, true));
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideCaption, result.DocumentTitle));
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideToolTip, result.DocumentTooltip));
            }

            windowFrame.Show();

            var openedDocument = textBuffer?.AsTextContainer().GetRelatedDocuments().FirstOrDefault();

            if (openedDocument != null)
            {
                var editorWorkspace   = openedDocument.Project.Solution.Workspace;
                var navigationService = editorWorkspace.Services.GetRequiredService <IDocumentNavigationService>();

                return(navigationService.TryNavigateToSpan(
                           editorWorkspace,
                           openedDocument.Id,
                           result.IdentifierLocation.SourceSpan,
                           options.WithChangedOption(NavigationOptions.PreferProvisionalTab, true),
                           cancellationToken));
            }

            return(true);
        }
        public bool TryNavigateToSymbol(ISymbol symbol, Project project, OptionSet options, CancellationToken cancellationToken)
        {
            if (project == null || symbol == null)
            {
                return(false);
            }

            options = options ?? project.Solution.Workspace.Options;
            symbol  = symbol.OriginalDefinition;

            // Prefer visible source locations if possible.
            var sourceLocations        = symbol.Locations.Where(loc => loc.IsInSource);
            var visibleSourceLocations = sourceLocations.Where(loc => loc.IsVisibleSourceLocation());
            var sourceLocation         = visibleSourceLocations.FirstOrDefault() ?? sourceLocations.FirstOrDefault();

            if (sourceLocation != null)
            {
                var targetDocument = project.Solution.GetDocument(sourceLocation.SourceTree);
                if (targetDocument != null)
                {
                    var editorWorkspace   = targetDocument.Project.Solution.Workspace;
                    var navigationService = editorWorkspace.Services.GetService <IDocumentNavigationService>();
                    return(navigationService.TryNavigateToSpan(editorWorkspace, targetDocument.Id, sourceLocation.SourceSpan, options));
                }
            }

            // We don't have a source document, so show the Metadata as Source view in a preview tab.

            var metadataLocation = symbol.Locations.Where(loc => loc.IsInMetadata).FirstOrDefault();

            if (metadataLocation == null || !_metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol))
            {
                return(false);
            }

            // Should we prefer navigating to the Object Browser over metadata-as-source?
            if (options.GetOption(VisualStudioNavigationOptions.NavigateToObjectBrowser, project.Language))
            {
                var libraryService = project.LanguageServices.GetService <ILibraryService>();
                if (libraryService == null)
                {
                    return(false);
                }

                var compilation = project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken);
                var navInfo     = libraryService.NavInfoFactory.CreateForSymbol(symbol, project, compilation);
                if (navInfo == null)
                {
                    navInfo = libraryService.NavInfoFactory.CreateForProject(project);
                }

                if (navInfo != null)
                {
                    var navigationTool = _serviceProvider.GetService <SVsObjBrowser, IVsNavigationTool>();
                    return(navigationTool.NavigateToNavInfo(navInfo) == VSConstants.S_OK);
                }

                // Note: we'll fallback to Metadata-As-Source if we fail to get IVsNavInfo, but that should never happen.
            }

            // Generate new source or retrieve existing source for the symbol in question
            var result = _metadataAsSourceFileService.GetGeneratedFileAsync(project, symbol, cancellationToken).WaitAndGetResult(cancellationToken);

            var vsRunningDocumentTable4 = _serviceProvider.GetService <SVsRunningDocumentTable, IVsRunningDocumentTable4>();
            var fileAlreadyOpen         = vsRunningDocumentTable4.IsMonikerValid(result.FilePath);

            var openDocumentService = _serviceProvider.GetService <SVsUIShellOpenDocument, IVsUIShellOpenDocument>();

            IVsUIHierarchy      hierarchy;
            uint                itemId;
            IOleServiceProvider localServiceProvider;
            IVsWindowFrame      windowFrame;

            openDocumentService.OpenDocumentViaProject(result.FilePath, VSConstants.LOGVIEWID.TextView_guid, out localServiceProvider, out hierarchy, out itemId, out windowFrame);

            var documentCookie = vsRunningDocumentTable4.GetDocumentCookie(result.FilePath);

            var vsTextBuffer = (IVsTextBuffer)vsRunningDocumentTable4.GetDocumentData(documentCookie);
            var textBuffer   = _editorAdaptersFactory.GetDataBuffer(vsTextBuffer);

            if (!fileAlreadyOpen)
            {
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_IsProvisional, true));
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideCaption, result.DocumentTitle));
                ErrorHandler.ThrowOnFailure(windowFrame.SetProperty((int)__VSFPROPID5.VSFPROPID_OverrideToolTip, result.DocumentTooltip));
            }

            windowFrame.Show();

            var openedDocument = textBuffer.AsTextContainer().GetRelatedDocuments().FirstOrDefault();

            if (openedDocument != null)
            {
                var editorWorkspace   = openedDocument.Project.Solution.Workspace;
                var navigationService = editorWorkspace.Services.GetService <IDocumentNavigationService>();

                return(navigationService.TryNavigateToSpan(
                           workspace: editorWorkspace,
                           documentId: openedDocument.Id,
                           textSpan: result.IdentifierLocation.SourceSpan,
                           options: options.WithChangedOption(NavigationOptions.PreferProvisionalTab, true)));
            }

            return(true);
        }
Exemplo n.º 12
0
        /// <summary>
        /// Internal for testing purposes.
        /// </summary>
        internal async Task <ImmutableArray <CodeDefinitionWindowLocation> > GetContextFromPointAsync(
            Document document, int position, CancellationToken cancellationToken)
        {
            var workspace      = document.Project.Solution.Workspace;
            var navigableItems = await GoToDefinitionHelpers.GetDefinitionsAsync(document, position, cancellationToken).ConfigureAwait(false);

            if (navigableItems?.Any() == true)
            {
                var navigationService = workspace.Services.GetRequiredService <IDocumentNavigationService>();

                using var _ = PooledObjects.ArrayBuilder <CodeDefinitionWindowLocation> .GetInstance(out var builder);

                foreach (var item in navigableItems)
                {
                    if (await navigationService.CanNavigateToSpanAsync(workspace, item.Document.Id, item.SourceSpan, cancellationToken).ConfigureAwait(false))
                    {
                        var text = await item.Document.GetTextAsync(cancellationToken).ConfigureAwait(false);

                        var linePositionSpan = text.Lines.GetLinePositionSpan(item.SourceSpan);

                        if (item.Document.FilePath != null)
                        {
                            builder.Add(new CodeDefinitionWindowLocation(item.DisplayTaggedParts.JoinText(), item.Document.FilePath, linePositionSpan.Start));
                        }
                    }
                }

                return(builder.ToImmutable());
            }

            // We didn't have regular source references, but possibly:
            // 1. Another language (like XAML) will take over via ISymbolNavigationService
            // 2. There are no locations from source, so we'll try to generate a metadata as source file and use that
            var symbol = await SymbolFinder.FindSymbolAtPositionAsync(
                document,
                position,
                cancellationToken : cancellationToken).ConfigureAwait(false);

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

            var symbolNavigationService = workspace.Services.GetRequiredService <ISymbolNavigationService>();
            var definitionItem          = symbol.ToNonClassifiedDefinitionItem(document.Project.Solution, includeHiddenLocations: false);
            var result = await symbolNavigationService.GetExternalNavigationSymbolLocationAsync(definitionItem, cancellationToken).ConfigureAwait(false);

            if (result != null)
            {
                return(ImmutableArray.Create(new CodeDefinitionWindowLocation(symbol.ToDisplayString(), result.Value.filePath, result.Value.linePosition)));
            }
            else if (_metadataAsSourceFileService.IsNavigableMetadataSymbol(symbol))
            {
                var allowDecompilation = _globalOptions.GetOption(FeatureOnOffOptions.NavigateToDecompiledSources);
                var declarationFile    = await _metadataAsSourceFileService.GetGeneratedFileAsync(document.Project, symbol, signaturesOnly : false, allowDecompilation, cancellationToken).ConfigureAwait(false);

                var identifierSpan = declarationFile.IdentifierLocation.GetLineSpan().Span;
                return(ImmutableArray.Create(new CodeDefinitionWindowLocation(symbol.ToDisplayString(), declarationFile.FilePath, identifierSpan.Start)));
            }

            return(ImmutableArray <CodeDefinitionWindowLocation> .Empty);
        }