public TagComputer(
                ITextBuffer subjectBuffer,
                IForegroundNotificationService notificationService,
                IAsynchronousOperationListener asyncListener,
                ClassificationTypeMap typeMap,
                SyntacticClassificationTaggerProvider taggerProvider)
            {
                _subjectBuffer = subjectBuffer;
                _notificationService = notificationService;
                _listener = asyncListener;
                _typeMap = typeMap;
                _taggerProvider = taggerProvider;

                _workQueue = new AsynchronousSerialWorkQueue(asyncListener);
                _reportChangeCancellationSource = new CancellationTokenSource();

                _lastLineCache = new LastLineCache();

                _workspaceRegistration = Workspace.GetWorkspaceRegistration(subjectBuffer.AsTextContainer());
                _workspaceRegistration.WorkspaceChanged += OnWorkspaceRegistrationChanged;

                if (_workspaceRegistration.Workspace != null)
                {
                    ConnectToWorkspace(_workspaceRegistration.Workspace);
                }
            }
예제 #2
0
        /// <summary>
        /// This should be called when a new document is opened in the IDE.
        /// </summary>
        public void OnDocumentOpened(string filePath, ITextBuffer buffer)
        {
            var textContainer = buffer?.AsTextContainer();

            if (!IsSupportedDocument(filePath) || textContainer == null)
            {
                return;
            }

            var workspaceRegistration = GetWorkspaceRegistration(textContainer);

            // Check if the document is already registered as open
            if (openDocuments.ContainsKey(workspaceRegistration))
            {
                return;
            }

            workspaceRegistration.WorkspaceChanged += Registration_WorkspaceChanged;

            var openDocumentInfo = new OpenDocumentInfo {
                SourceTextContainer = textContainer,
                FilePath            = filePath
            };

            openDocuments[workspaceRegistration] = openDocumentInfo;

            if (workspaceRegistration.Workspace != null)
            {
                return;
            }

            AddDocument(workspaceRegistration, openDocumentInfo);
        }
            public bool TryGetTextUndoHistory(Workspace editorWorkspace, ITextBuffer textBuffer, out ITextUndoHistory undoHistory)
            {
                undoHistory = null;

                if (!(editorWorkspace is VisualStudioWorkspaceImpl) &&
                    !(editorWorkspace is MiscellaneousFilesWorkspace))
                {
                    return false;
                }

                // TODO: Handle undo if context changes
                var documentId = editorWorkspace.GetDocumentIdInCurrentContext(textBuffer.AsTextContainer());
                if (documentId == null)
                {
                    return false;
                }

                var document = GetDocument(editorWorkspace, documentId);
                if (document == null)
                {
                    return false;
                }

                undoHistory = document.GetTextUndoHistory();
                return true;
            }
예제 #4
0
        public NavigationBarController(
            INavigationBarPresenter presenter,
            ITextBuffer subjectBuffer,
            IWaitIndicator waitIndicator,
            IAsynchronousOperationListener asyncListener)
        {
            _presenter = presenter;
            _subjectBuffer = subjectBuffer;
            _waitIndicator = waitIndicator;
            _asyncListener = asyncListener;
            _workspaceRegistration = Workspace.GetWorkspaceRegistration(subjectBuffer.AsTextContainer());
            _workspaceRegistration.WorkspaceChanged += OnWorkspaceRegistrationChanged;

            presenter.CaretMoved += OnCaretMoved;
            presenter.ViewFocused += OnViewFocused;

            presenter.DropDownFocused += OnDropDownFocused;
            presenter.ItemSelected += OnItemSelected;

            subjectBuffer.PostChanged += OnSubjectBufferPostChanged;

            // Initialize the tasks to be an empty model so we never have to deal with a null case.
            _modelTask = Task.FromResult(
                new NavigationBarModel(
                    SpecializedCollections.EmptyList<NavigationBarItem>(),
                    default(VersionStamp),
                    null));

            _selectedItemInfoTask = Task.FromResult(new NavigationBarSelectedTypeAndMember(null, null));

            if (_workspaceRegistration.Workspace != null)
            {
                ConnectToWorkspace(_workspaceRegistration.Workspace);
            }
        }
예제 #5
0
        ///<summary>Creates a new document linked to an existing text buffer.</summary>
        public DocumentId CreateDocument(ProjectId projectId, ITextBuffer buffer, string debugName = null)
        {
            var id = DocumentId.CreateNewId(projectId, debugName);

            TryApplyChanges(CurrentSolution.AddDocument(id, debugName ?? "Sample Document", TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create())));
            OpenDocument(id, buffer);
            return id;
        }
예제 #6
0
            ///<summary>Creates a new document linked to an existing text buffer.</summary>
            public DocumentId CreateDocument(ProjectId projectId, ITextBuffer buffer)
            {
                // Our GetFileName() extension (which should probably be deleted) doesn't work on projection buffers
                var debugName = TextBufferExtensions.GetFileName(buffer) ?? "Markdown Embedded Code";
                var id = DocumentId.CreateNewId(projectId, debugName);

                TryApplyChanges(CurrentSolution.AddDocument(
                    id, debugName,
                    TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create())
                ));
                OpenDocument(id, buffer);
                return id;
            }
예제 #7
0
            ///<summary>Creates a new document linked to an existing text buffer.</summary>
            public Document CreateDocument(ProjectId projectId, ITextBuffer buffer)
            {
                var id = DocumentId.CreateNewId(projectId);
                documentBuffers.Add(id, buffer);

                // Our GetFileName() extension (which should probably be deleted) doesn't work on projection buffers
                var docInfo = DocumentInfo.Create(id, TextBufferExtensions.GetFileName(buffer) ?? "Markdown Embedded Code",
                    loader: TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create()),
                    sourceCodeKind: SourceCodeKind.Script
                );
                OnDocumentAdded(docInfo);
                OnDocumentOpened(id, buffer.AsTextContainer());
                buffer.Changed += delegate { OnDocumentContextUpdated(id); };
                return CurrentSolution.GetDocument(id);
            }
예제 #8
0
        /// <summary>
        /// This should be called when an open document in the IDE is closed.
        /// </summary>
        public void OnDocumentClosed(string filePath, ITextBuffer buffer)
        {
            var textContainer = buffer?.AsTextContainer();

            if (!IsSupportedDocument(filePath) || textContainer == null)
            {
                return;
            }

            var workspaceRegistration = GetWorkspaceRegistration(textContainer);

            workspaceRegistration.WorkspaceChanged -= Registration_WorkspaceChanged;

            if (openDocuments.TryRemove(workspaceRegistration, out var openDocumentInfo))
            {
                RemoveDocument(openDocumentInfo);
            }
        }
예제 #9
0
        private void OnWorkspaceChanged(object sender, WorkspaceChangeEventArgs args)
        {
            // We're getting an event for a workspace we already disconnected from
            if (args.NewSolution.Workspace != _workspace)
            {
                return;
            }

            // If the displayed project is being renamed, retrigger the update
            if (args.Kind == WorkspaceChangeKind.ProjectChanged && args.ProjectId != null)
            {
                var oldProject = args.OldSolution.GetProject(args.ProjectId);
                var newProject = args.NewSolution.GetProject(args.ProjectId);

                if (oldProject.Name != newProject.Name)
                {
                    var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer());

                    if (currentContextDocumentId != null && currentContextDocumentId.ProjectId == args.ProjectId)
                    {
                        StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0, selectedItemUpdateDelay: 0, updateUIWhenDone: true);
                    }
                }
            }

            if (args.Kind == WorkspaceChangeKind.DocumentChanged &&
                args.OldSolution == args.NewSolution)
            {
                var currentContextDocumentId = _workspace.GetDocumentIdInCurrentContext(_subjectBuffer.AsTextContainer());
                if (currentContextDocumentId != null && currentContextDocumentId == args.DocumentId)
                {
                    // The context has changed, so update everything.
                    StartModelUpdateAndSelectedItemUpdateTasks(modelUpdateDelay: 0, selectedItemUpdateDelay: 0, updateUIWhenDone: true);
                }
            }
        }
예제 #10
0
        private IncludeDirectiveTriviaSyntax GetIncludeDirective(ITextView textView, ITextBuffer textBuffer)
        {
            var document = textBuffer.AsTextContainer().GetOpenDocumentInCurrentContext();

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

            var caretPoint = textView.GetCaretPoint(textBuffer);

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

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

            var sourceLocation = syntaxTree.MapRootFilePosition(caretPoint.Value.Position);

            var syntaxToken = (SyntaxToken)syntaxTree.Root.FindToken(sourceLocation, true);

            if (syntaxToken.Parent == null || syntaxToken.Parent.Kind != SyntaxKind.IncludeDirectiveTrivia)
            {
                return(null);
            }

            var includeDirectiveTrivia = (IncludeDirectiveTriviaSyntax)syntaxToken.Parent;

            if (includeDirectiveTrivia.Filename != syntaxToken)
            {
                return(null);
            }

            return(includeDirectiveTrivia);
        }
예제 #11
0
        async Task InitializeAsync(ITextBuffer buffer, string code, MetadataReference[] refs, string languageName, ISynchronousTagger <IClassificationTag> tagger, CompilationOptions compilationOptions, ParseOptions parseOptions)
        {
            using (var workspace = new AdhocWorkspace(RoslynMefHostServices.DefaultServices)) {
                var documents = new List <DocumentInfo>();
                var projectId = ProjectId.CreateNewId();
                documents.Add(DocumentInfo.Create(DocumentId.CreateNewId(projectId), "main.cs", null, SourceCodeKind.Regular, TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create())));

                var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Create(), "compilecodeproj", Guid.NewGuid().ToString(), languageName,
                                                     compilationOptions: compilationOptions
                                                     .WithOptimizationLevel(OptimizationLevel.Release)
                                                     .WithPlatform(Platform.AnyCpu)
                                                     .WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default),
                                                     parseOptions: parseOptions,
                                                     documents: documents,
                                                     metadataReferences: refs,
                                                     isSubmission: false, hostObjectType: null);
                workspace.AddProject(projectInfo);
                foreach (var doc in documents)
                {
                    workspace.OpenDocument(doc.Id);
                }

                buffer.Replace(new Span(0, buffer.CurrentSnapshot.Length), code);

                {
                    // Initialize classification code paths
                    var spans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length));
                    foreach (var tagSpan in tagger.GetTags(spans, CancellationToken.None))
                    {
                    }
                }

                {
                    // Initialize completion code paths
                    var info = CompletionInfo.Create(buffer.CurrentSnapshot);
                    Debug.Assert(info != null);
                    if (info != null)
                    {
                        var completionTrigger = CompletionTrigger.Invoke;
                        var completionList    = await info.Value.CompletionService.GetCompletionsAsync(info.Value.Document, 0, completionTrigger);
                    }
                }

                {
                    // Initialize signature help code paths
                    var info = SignatureHelpInfo.Create(buffer.CurrentSnapshot);
                    Debug.Assert(info != null);
                    if (info != null)
                    {
                        int sigHelpIndex = code.IndexOf("sighelp");
                        Debug.Assert(sigHelpIndex >= 0);
                        var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand);
                        var items       = await info.Value.SignatureHelpService.GetItemsAsync(info.Value.Document, sigHelpIndex, triggerInfo);
                    }
                }

                {
                    // Initialize quick info code paths
                    var info = QuickInfoState.Create(buffer.CurrentSnapshot);
                    Debug.Assert(info != null);
                    if (info != null)
                    {
                        int quickInfoIndex = code.IndexOf("Equals");
                        Debug.Assert(quickInfoIndex >= 0);
                        var item = await info.Value.QuickInfoService.GetItemAsync(info.Value.Document, quickInfoIndex);
                    }
                }
            }
        }
예제 #12
0
        private void SetSubmissionDocument(ITextBuffer buffer, Project project)
        {
            // Try to unregister our buffer with our workspace. This is a bit of a hack,
            // but we may have registered the buffer with the workspace if it was
            // transitioned to an Interactive Command buffer.
            _workspace.UnregisterText(buffer.AsTextContainer());

            var documentId = DocumentId.CreateNewId(project.Id, debugName: project.Name);
            var solution = project.Solution
                .AddDocument(documentId, project.Name, buffer.CurrentSnapshot.AsText());

            _workspace.SetCurrentSolution(solution);

            // opening document will start workspace listening to changes in this text container
            _workspace.OpenDocument(documentId, buffer.AsTextContainer());
        }
예제 #13
0
 internal static bool TryGetWorkspace(this ITextBuffer buffer, out Workspace workspace)
 => Workspace.TryGetWorkspace(buffer.AsTextContainer(), out workspace);
예제 #14
0
 void IVisualStudioWorkspaceHost.OnDocumentOpened(DocumentId documentId, ITextBuffer textBuffer, bool currentContext)
 {
     SubscribeToSharedHierarchyEvents(documentId);
     _workspace.OnDocumentOpened(documentId, textBuffer.AsTextContainer(), currentContext);
 }
            public Source(SuggestedActionsSourceProvider owner, ITextView textView, ITextBuffer textBuffer)
            {
                _owner = owner;
                _textView = textView;
                _textView.Closed += OnTextViewClosed;

                _subjectBuffer = textBuffer;
                _registration = Workspace.GetWorkspaceRegistration(textBuffer.AsTextContainer());

                _lastSolutionVersionReported = InvalidSolutionVersion;
                var updateSource = (IDiagnosticUpdateSource)_owner._diagnosticService;
                updateSource.DiagnosticsUpdated += OnDiagnosticsUpdated;

                if (_registration.Workspace != null)
                {
                    _workspace = _registration.Workspace;
                    _workspace.DocumentActiveContextChanged += OnActiveContextChanged;
                }

                _registration.WorkspaceChanged += OnWorkspaceChanged;
            }
예제 #16
0
 ///<summary>Links an existing <see cref="Document"/> to an <see cref="ITextBuffer"/>, synchronizing their contents.</summary>
 public void OpenDocument(DocumentId documentId, ITextBuffer buffer)
 {
     documentBuffers.Add(documentId, buffer);
     OnDocumentOpened(documentId, buffer.AsTextContainer());
     buffer.Changed += delegate { OnDocumentContextUpdated(documentId); };
 }
예제 #17
0
        public virtual object GetPreview(CancellationToken cancellationToken)
        {
            var extensionManager = this.Workspace.Services.GetService <IExtensionManager>();
            var previewContent   = extensionManager.PerformFunction(Provider, () =>
            {
                var previewResult = GetPreviewResult(cancellationToken);
                if (previewResult == null)
                {
                    return(null);
                }
                else
                {
                    var preferredDocumentId = Workspace.GetDocumentIdInCurrentContext(SubjectBuffer.AsTextContainer());
                    var preferredProjectid  = preferredDocumentId == null ? null : preferredDocumentId.ProjectId;

                    return(previewResult.TakeNextPreview(preferredDocumentId, preferredProjectid));
                }
            });

            var optionService = Workspace.Services.GetService <IOptionService>();

            if (optionService == null || !optionService.GetOption(InternalFeatureOnOffOptions.EnhancedPreviewPane))
            {
                return(previewContent);
            }

            var previewPaneService = Workspace.Services.GetService <IPreviewPaneService>();

            if (previewPaneService == null)
            {
                return(previewContent);
            }

            return(previewPaneService.GetPreviewPane(GetDiagnostic(), previewContent));
        }
예제 #18
0
 /// <summary>
 /// Returns the workspace or null
 /// </summary>
 /// <param name="buffer">Text buffer</param>
 /// <returns></returns>
 public static Workspace TryGetWorkspace(this ITextBuffer buffer)
 {
     Workspace.TryGetWorkspace(buffer.AsTextContainer(), out var ws);
     return(ws);
 }
예제 #19
0
 internal static bool CanApplyChangeDocumentToWorkspace(this ITextBuffer buffer) =>
 Workspace.TryGetWorkspace(buffer.AsTextContainer(), out var workspace) &&
 workspace.CanApplyChange(ApplyChangesKind.ChangeDocument);
예제 #20
0
        ///<summary>Creates a new document linked to an existing text buffer.</summary>
        public DocumentId CreateDocument(ProjectId projectId, ITextBuffer buffer, string debugName = null)
        {
            var id = DocumentId.CreateNewId(projectId, debugName);

            TryApplyChanges(CurrentSolution.AddDocument(id, debugName ?? "Sample Document", TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create())));
            OpenDocument(id, buffer);
            return(id);
        }
예제 #21
0
            public TagSource(
                ITextView?textView,
                ITextBuffer subjectBuffer,
                ITextBufferVisibilityTracker?visibilityTracker,
                AbstractAsynchronousTaggerProvider <TTag> dataSource,
                IAsynchronousOperationListener asyncListener)
            {
                dataSource.ThreadingContext.ThrowIfNotOnUIThread();
                if (dataSource.SpanTrackingMode == SpanTrackingMode.Custom)
                {
                    throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
                }

                _textView          = textView;
                _subjectBuffer     = subjectBuffer;
                _visibilityTracker = visibilityTracker;
                _dataSource        = dataSource;
                _asyncListener     = asyncListener;

                _workspaceRegistration = Workspace.GetWorkspaceRegistration(subjectBuffer.AsTextContainer());

                // Collapse all booleans added to just a max of two ('true' or 'false') representing if we're being
                // asked for initial tags or not
                _eventChangeQueue = new AsyncBatchingWorkQueue <bool>(
                    dataSource.EventChangeDelay.ComputeTimeDelay(),
                    ProcessEventChangeAsync,
                    EqualityComparer <bool> .Default,
                    asyncListener,
                    _disposalTokenSource.Token);

                _highPriTagsChangedQueue = new AsyncBatchingWorkQueue <NormalizedSnapshotSpanCollection>(
                    TaggerDelay.NearImmediate.ComputeTimeDelay(),
                    ProcessTagsChangedAsync,
                    equalityComparer: null,
                    asyncListener,
                    _disposalTokenSource.Token);

                if (_dataSource.AddedTagNotificationDelay == TaggerDelay.NearImmediate)
                {
                    // if the tagger wants "added tags" to be reported "NearImmediate"ly, then just reuse
                    // the "high pri" queue as that already reports things at that cadence.
                    _normalPriTagsChangedQueue = _highPriTagsChangedQueue;
                }
                else
                {
                    _normalPriTagsChangedQueue = new AsyncBatchingWorkQueue <NormalizedSnapshotSpanCollection>(
                        _dataSource.AddedTagNotificationDelay.ComputeTimeDelay(),
                        ProcessTagsChangedAsync,
                        equalityComparer: null,
                        asyncListener,
                        _disposalTokenSource.Token);
                }

                DebugRecordInitialStackTrace();

                // Create the tagger-specific events that will cause the tagger to refresh.
                _eventSource = CreateEventSource();

                // any time visibility changes, resume tagging on all taggers.  Any non-visible taggers will pause
                // themselves immediately afterwards.
                _onVisibilityChanged = () => ResumeIfVisible();

                // Now hook up this tagger to all interesting events.
                Connect();

                // Now that we're all hooked up to the events we care about, start computing the initial set of tags at
                // high priority.  We want to get the UI to a complete state as soon as possible.
                EnqueueWork(highPriority: true);

                return;

                // Represented as a local function just so we can keep this in sync with Dispose.Disconnect below.
                void Connect()
                {
                    _dataSource.ThreadingContext.ThrowIfNotOnUIThread();

                    // Register to hear about visibility changes so we can pause/resume this tagger.
                    _visibilityTracker?.RegisterForVisibilityChanges(subjectBuffer, _onVisibilityChanged);

                    _eventSource.Changed += OnEventSourceChanged;

                    if (_dataSource.TextChangeBehavior.HasFlag(TaggerTextChangeBehavior.TrackTextChanges))
                    {
                        _subjectBuffer.Changed += OnSubjectBufferChanged;
                    }

                    if (_dataSource.CaretChangeBehavior.HasFlag(TaggerCaretChangeBehavior.RemoveAllTagsOnCaretMoveOutsideOfTag))
                    {
                        if (_textView == null)
                        {
                            throw new ArgumentException(
                                      nameof(_dataSource.CaretChangeBehavior) + " can only be specified for an " + nameof(IViewTaggerProvider));
                        }

                        _textView.Caret.PositionChanged += OnCaretPositionChanged;
                    }

                    // Tell the interaction object to start issuing events.
                    _eventSource.Connect();
                }
            }
 protected AbstractWorkspaceTrackingTaggerEventSource(ITextBuffer subjectBuffer, TaggerDelay delay) : base(delay)
 {
     this.SubjectBuffer = subjectBuffer;
     _workspaceRegistration = Workspace.GetWorkspaceRegistration(subjectBuffer.AsTextContainer());
 }
예제 #23
0
 /// <summary>
 /// Returns the name of the language (see <see cref="LanguageNames"/>) associated with the specified buffer.
 /// </summary>
 internal static string?GetLanguageName(this ITextBuffer buffer)
 => Workspace.TryGetWorkspace(buffer.AsTextContainer(), out var workspace) ?
 workspace.Services.GetLanguageServices(buffer.ContentType)?.Language : null;
            /// <summary>
            /// We do all mutation work on the UI thread.  That ensures that all mutation
            /// is processed serially *and* it means we can safely examine things like
            /// subject buffers and open documents without any threat of race conditions.
            /// Note that we do not do any expensive work here.  We just store (or remove)
            /// the data we were given in appropriate buckets.
            ///
            /// For example, we create a TaggerProvider per unique DiagnosticUpdatedArgs.Id
            /// we get.  So if we see a new id we simply create a tagger for it and pass it
            /// these args to store.  Otherwise we pass these args to the existing tagger.
            ///
            /// Similarly, clearing out data is just a matter of us clearing our reference
            /// to the data.
            /// </summary>
            private void OnDiagnosticsUpdatedOnForeground(DiagnosticsUpdatedArgs e)
            {
                this.AssertIsForeground();

                if (_disposed)
                {
                    return;
                }

                // Do some quick checks to avoid doing any further work for diagnostics  we don't
                // care about.
                var ourDocument   = _subjectBuffer.AsTextContainer().GetOpenDocumentInCurrentContext();
                var ourDocumentId = ourDocument?.Id;

                if (ourDocumentId != _currentDocumentId)
                {
                    // Our buffer has started tracking some other document entirely.
                    // We have to clear out all of the diagnostics we have currently stored.
                    RemoveAllCachedDiagnostics();
                }

                _currentDocumentId = ourDocumentId;

                // Now see if the document we're tracking corresponds to the diagnostics
                // we're hearing about.  If not, just ignore them.
                if (ourDocument == null ||
                    ourDocument.Project.Solution.Workspace != e.Workspace ||
                    ourDocument.Id != e.DocumentId)
                {
                    return;
                }

                // We're hearing about diagnostics for our document.  We may be hearing
                // about new diagnostics coming, or existing diagnostics being cleared
                // out.

                // First see if this is a document/project removal.  If so, clear out any state we
                // have associated with any analyzers we have for that document/project.
                ProcessRemovedDiagnostics(e);

                // Make sure we can find an editor snapshot for these errors.  Otherwise we won't
                // be able to make ITagSpans for them.  If we can't, just bail out.  This happens
                // when the solution crawler is very far behind.  However, it will have a more
                // up to date document within it that it will eventually process.  Until then
                // we just keep around the stale tags we have.
                //
                // Note: if the Solution or Document is null here, then that means the document
                // was removed.  In that case, we do want to proceed so that we'll produce 0
                // tags and we'll update the editor appropriately.
                SourceText    sourceText     = null;
                ITextSnapshot editorSnapshot = null;

                if (e.Solution != null)
                {
                    var diagnosticDocument = e.Solution.GetDocument(e.DocumentId);
                    if (diagnosticDocument != null)
                    {
                        if (!diagnosticDocument.TryGetText(out sourceText))
                        {
                            return;
                        }

                        editorSnapshot = sourceText.FindCorrespondingEditorTextSnapshot();
                        if (editorSnapshot == null)
                        {
                            return;
                        }

                        // Make sure the editor we've got associated with these diagnostics is the
                        // same one we're a tagger for.  It is possible for us to hear about diagnostics
                        // for the *same* Document that are not from the *same* buffer.  For example,
                        // say we have the following chain of events:
                        //
                        //      Document is opened.
                        //      Diagnostics start analyzing.
                        //      Document is closed.
                        //      Document is opened.
                        //      Diagnostics finish and report for document.
                        //
                        // We'll hear about diagnostics for the original Document/Buffer that was
                        // opened.  But we'll be trying to apply them to this current Document/Buffer.
                        // That won't work since these will be different buffers (and thus, we won't
                        // be able to map the diagnostic spans appropriately).
                        //
                        // Note: returning here is safe.  Because the file is closed/opened, The
                        // Diagnostics Service will reanalyze it.  It will then report the new results
                        // which we will hear about and use.
                        if (editorSnapshot.TextBuffer != _subjectBuffer)
                        {
                            return;
                        }
                    }
                }

                OnDiagnosticsUpdatedOnForeground(e, sourceText, editorSnapshot);
            }
예제 #25
0
 internal static bool TryGetWorkspace(this ITextBuffer buffer, [NotNullWhen(true)] out Workspace?workspace)
 => Workspace.TryGetWorkspace(buffer.AsTextContainer(), out workspace);
예제 #26
0
 SourceTextContainer ISourceTextHelper.AsTextContainer(ITextBuffer buffer) => buffer.AsTextContainer();
예제 #27
0
        public virtual async Task <object> GetPreviewAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            // Light bulb will always invoke this function on the UI thread.
            AssertIsForeground();

            var extensionManager = this.Workspace.Services.GetService <IExtensionManager>();
            var previewContent   = await extensionManager.PerformFunctionAsync(Provider, async() =>
            {
                // We need to stay on UI thread after GetPreviewResultAsync() so that TakeNextPreviewAsync()
                // below can execute on UI thread. We use ConfigureAwait(true) to stay on the UI thread.
                var previewResult = await GetPreviewResultAsync(cancellationToken).ConfigureAwait(true);
                if (previewResult == null)
                {
                    return(null);
                }
                else
                {
                    var preferredDocumentId = Workspace.GetDocumentIdInCurrentContext(SubjectBuffer.AsTextContainer());
                    var preferredProjectid  = preferredDocumentId == null ? null : preferredDocumentId.ProjectId;

                    // TakeNextPreviewAsync() needs to run on UI thread.
                    AssertIsForeground();
                    return(await previewResult.TakeNextPreviewAsync(preferredDocumentId, preferredProjectid, cancellationToken).ConfigureAwait(true));
                }

                // GetPreviewPane() below needs to run on UI thread. We use ConfigureAwait(true) to stay on the UI thread.
            }, defaultValue : null).ConfigureAwait(true);

            var previewPaneService = Workspace.Services.GetService <IPreviewPaneService>();

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

            cancellationToken.ThrowIfCancellationRequested();

            // GetPreviewPane() needs to run on the UI thread.
            AssertIsForeground();
            return(previewPaneService.GetPreviewPane(GetDiagnostic(), previewContent));
        }
        public EditorDocument(
            EditorDocumentManager documentManager,
            ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
            JoinableTaskContext joinableTaskContext,
            string projectFilePath,
            string documentFilePath,
            TextLoader textLoader,
            FileChangeTracker fileTracker,
            ITextBuffer textBuffer,
            EventHandler changedOnDisk,
            EventHandler changedInEditor,
            EventHandler opened,
            EventHandler closed)
        {
            if (documentManager is null)
            {
                throw new ArgumentNullException(nameof(documentManager));
            }

            if (projectSnapshotManagerDispatcher is null)
            {
                throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
            }

            if (joinableTaskContext is null)
            {
                throw new ArgumentNullException(nameof(joinableTaskContext));
            }

            if (projectFilePath is null)
            {
                throw new ArgumentNullException(nameof(projectFilePath));
            }

            if (documentFilePath is null)
            {
                throw new ArgumentNullException(nameof(documentFilePath));
            }

            if (textLoader is null)
            {
                throw new ArgumentNullException(nameof(textLoader));
            }

            if (fileTracker is null)
            {
                throw new ArgumentNullException(nameof(fileTracker));
            }

            _documentManager = documentManager;
            _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher;
            _joinableTaskContext = joinableTaskContext;
            ProjectFilePath      = projectFilePath;
            DocumentFilePath     = documentFilePath;
            TextLoader           = textLoader;
            _fileTracker         = fileTracker;
            _changedOnDisk       = changedOnDisk;
            _changedInEditor     = changedInEditor;
            _opened = opened;
            _closed = closed;

            _snapshotTracker      = new SnapshotChangeTracker();
            _fileTracker.Changed += ChangeTracker_Changed;

            // Only one of these should be active at a time.
            if (textBuffer == null)
            {
                _ = _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(
                    () => _fileTracker.StartListening(), CancellationToken.None).ConfigureAwait(false);
            }
            else
            {
                _snapshotTracker.StartTracking(textBuffer);

                EditorTextBuffer                 = textBuffer;
                EditorTextContainer              = textBuffer.AsTextContainer();
                EditorTextContainer.TextChanged += TextContainer_Changed;
            }
        }
예제 #29
0
		async Task InitializeAsync(ITextBuffer buffer, string code, MetadataReference[] refs, string languageName, ISynchronousTagger<IClassificationTag> tagger, CompilationOptions compilationOptions, ParseOptions parseOptions) {
			using (var workspace = new AdhocWorkspace(RoslynMefHostServices.DefaultServices)) {
				var documents = new List<DocumentInfo>();
				var projectId = ProjectId.CreateNewId();
				documents.Add(DocumentInfo.Create(DocumentId.CreateNewId(projectId), "main.cs", null, SourceCodeKind.Regular, TextLoader.From(buffer.AsTextContainer(), VersionStamp.Create())));

				var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Create(), "compilecodeproj", Guid.NewGuid().ToString(), languageName,
					compilationOptions: compilationOptions
							.WithOptimizationLevel(OptimizationLevel.Release)
							.WithPlatform(Platform.AnyCpu)
							.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default),
					parseOptions: parseOptions,
					documents: documents,
					metadataReferences: refs,
					isSubmission: false, hostObjectType: null);
				workspace.AddProject(projectInfo);
				foreach (var doc in documents)
					workspace.OpenDocument(doc.Id);

				buffer.Replace(new Span(0, buffer.CurrentSnapshot.Length), code);

				{
					// Initialize classification code paths
					var spans = new NormalizedSnapshotSpanCollection(new SnapshotSpan(buffer.CurrentSnapshot, 0, buffer.CurrentSnapshot.Length));
					foreach (var tagSpan in tagger.GetTags(spans, CancellationToken.None)) { }
				}

				{
					// Initialize completion code paths
					var info = CompletionInfo.Create(buffer.CurrentSnapshot);
					Debug.Assert(info != null);
					if (info != null) {
						var completionTrigger = CompletionTrigger.Default;
						var completionList = await info.Value.CompletionService.GetCompletionsAsync(info.Value.Document, 0, completionTrigger);
					}
				}

				{
					// Initialize signature help code paths
					var info = SignatureHelpInfo.Create(buffer.CurrentSnapshot);
					Debug.Assert(info != null);
					if (info != null) {
						int sigHelpIndex = code.IndexOf("sighelp");
						Debug.Assert(sigHelpIndex >= 0);
						var triggerInfo = new SignatureHelpTriggerInfo(SignatureHelpTriggerReason.InvokeSignatureHelpCommand);
						var items = await info.Value.SignatureHelpService.GetItemsAsync(info.Value.Document, sigHelpIndex, triggerInfo);
					}
				}

				{
					// Initialize quick info code paths
					var info = QuickInfoState.Create(buffer.CurrentSnapshot);
					Debug.Assert(info != null);
					if (info != null) {
						int quickInfoIndex = code.IndexOf("Equals");
						Debug.Assert(quickInfoIndex >= 0);
						var item = await info.Value.QuickInfoService.GetItemAsync(info.Value.Document, quickInfoIndex);
					}
				}
			}
		}
            public TagComputer(
                ITextBuffer subjectBuffer,
                IForegroundNotificationService notificationService,
                IAsynchronousOperationListener asyncListener,
                ClassificationTypeMap typeMap,
                SyntacticClassificationTaggerProvider taggerProvider,
                IViewSupportsClassificationService viewSupportsClassificationServiceOpt,
                ITextBufferAssociatedViewService associatedViewService,
                IEditorClassificationService editorClassificationService,
                string languageName)
            {
                _subjectBuffer = subjectBuffer;
                _notificationService = notificationService;
                _listener = asyncListener;
                _typeMap = typeMap;
                _taggerProvider = taggerProvider;
                _viewSupportsClassificationServiceOpt = viewSupportsClassificationServiceOpt;
                _associatedViewService = associatedViewService;
                _editorClassificationService = editorClassificationService;
                _languageName = languageName;

                _workQueue = new AsynchronousSerialWorkQueue(asyncListener);
                _reportChangeCancellationSource = new CancellationTokenSource();

                _lastLineCache = new LastLineCache();

                _workspaceRegistration = Workspace.GetWorkspaceRegistration(subjectBuffer.AsTextContainer());
                _workspaceRegistration.WorkspaceChanged += OnWorkspaceRegistrationChanged;

                ConnectToWorkspace(_workspaceRegistration.Workspace);
            }
예제 #31
0
 public SourceTextContainer GetOpenTextContainer()
 {
     return(_openTextBuffer.AsTextContainer());
 }
예제 #32
0
        public EditorDocument(
            EditorDocumentManager documentManager,
            string projectFilePath,
            string documentFilePath,
            TextLoader textLoader,
            FileChangeTracker fileTracker,
            ITextBuffer textBuffer,
            EventHandler changedOnDisk,
            EventHandler changedInEditor,
            EventHandler opened,
            EventHandler closed)
        {
            if (documentManager == null)
            {
                throw new ArgumentNullException(nameof(documentManager));
            }

            if (projectFilePath == null)
            {
                throw new ArgumentNullException(nameof(projectFilePath));
            }

            if (documentFilePath == null)
            {
                throw new ArgumentNullException(nameof(documentFilePath));
            }

            if (textLoader == null)
            {
                throw new ArgumentNullException(nameof(textLoader));
            }

            if (fileTracker == null)
            {
                throw new ArgumentNullException(nameof(fileTracker));
            }

            _documentManager = documentManager;
            ProjectFilePath  = projectFilePath;
            DocumentFilePath = documentFilePath;
            TextLoader       = textLoader;
            _fileTracker     = fileTracker;
            _changedOnDisk   = changedOnDisk;
            _changedInEditor = changedInEditor;
            _opened          = opened;
            _closed          = closed;

            _snapshotTracker      = new SnapshotChangeTracker();
            _fileTracker.Changed += ChangeTracker_Changed;

            // Only one of these should be active at a time.
            if (textBuffer == null)
            {
                _fileTracker.StartListening();
            }
            else
            {
                _snapshotTracker.StartTracking(textBuffer);

                EditorTextBuffer                 = textBuffer;
                EditorTextContainer              = textBuffer.AsTextContainer();
                EditorTextContainer.TextChanged += TextContainer_Changed;
            }
        }
예제 #33
0
 void IVisualStudioWorkspaceHost.OnAdditionalDocumentOpened(DocumentId documentId, ITextBuffer textBuffer, bool isCurrentContext)
 {
     _workspace.OnAdditionalDocumentOpened(documentId, textBuffer.AsTextContainer(), isCurrentContext);
 }
예제 #34
0
 protected AbstractWorkspaceTrackingTaggerEventSource(ITextBuffer subjectBuffer, TaggerDelay delay) : base(delay)
 {
     this.SubjectBuffer     = subjectBuffer;
     _workspaceRegistration = Workspace.GetWorkspaceRegistration(subjectBuffer.AsTextContainer());
 }
예제 #35
0
 /// <summary>
 /// Gets the <see cref="Document"/>s from the corresponding <see cref="Workspace.CurrentSolution"/> that are associated with the <see cref="ITextBuffer"/>.
 /// There may be multiple <see cref="Document"/>s associated with the buffer if it is linked into multiple projects or is part of a Shared Project.
 /// </summary>
 public static IEnumerable <Document> GetRelatedDocuments(this ITextBuffer buffer) =>
 buffer.AsTextContainer().GetRelatedDocuments();
예제 #36
0
        private bool Update()
        {
            // Update is called when the state of any of our surrounding systems changes. Here we want to examine the
            // state of the world and then update properties as necessary.
            //
            // Fundamentally we have a Razor half of the world as as soon as the document is open - and then later
            // the C# half of the world will be initialized. This code is in general pretty tolerant of
            // unexpected /impossible states.
            //
            // We also want to successfully shut down when the buffer is renamed to something other .cshtml.

            // If there's no Razor buffer, then there's really nothing to do. This isn't a Razor file.
            var razorBuffer = _textView.BufferGraph.GetTextBuffers(IsRazorBuffer).FirstOrDefault();

            // The source container is tied to the Razor buffer since that's what we want to watch for changes.
            SourceTextContainer textContainer = null;

            if (razorBuffer != null)
            {
                textContainer = razorBuffer.AsTextContainer();
            }

            bool isSupportedProject = false;

            if (razorBuffer != null)
            {
                // The project can be null when the document is in the process of closing.
                var project = _service.GetProject(razorBuffer);

                if (project != null)
                {
                    isSupportedProject = _service.IsSupportedProject(project);
                }
            }

            // The C# buffer is the other buffer in the graph that is C# (only if we already found a Razor buffer).
            // We're not currently validating that it's a child of the Razor buffer even though we expect that.
            ITextBuffer cSharpBuffer = null;

            if (razorBuffer != null)
            {
                cSharpBuffer = _textView.BufferGraph.GetTextBuffers(IsCSharpBuffer).FirstOrDefault();
            }

            // Now if we have a C# buffer we want to watch for it be attached to a workspace.
            SourceTextContainer   cSharpTextContainer   = null;
            WorkspaceRegistration workspaceRegistration = null;

            if (cSharpBuffer != null)
            {
                cSharpTextContainer = cSharpBuffer.AsTextContainer();
                Debug.Assert(cSharpTextContainer != null);

                workspaceRegistration = Workspace.GetWorkspaceRegistration(cSharpTextContainer);
            }

            // Now finally we can see if we have a workspace
            Workspace workspace = null;

            if (workspaceRegistration != null)
            {
                workspace = workspaceRegistration.Workspace;
            }

            // Now we know if the Roslyn state for this document has been initialized, let's look for a project.
            DocumentId documentId = null;

            if (cSharpTextContainer != null && workspace != null)
            {
                documentId = workspace.GetDocumentIdInCurrentContext(cSharpTextContainer);
            }

            // As a special case, we want to default to the VisualStudioWorkspace until we find out otherwise
            // This lets us start working before a project gets initialized.
            if (isSupportedProject && workspace == null)
            {
                workspace = _service.Workspace;
            }

            var changed = false;

            changed |= razorBuffer == _razorBuffer;
            changed |= textContainer == _textContainer;
            changed |= isSupportedProject == _isSupportedProject;
            changed |= cSharpBuffer == _cSharpBuffer;
            changed |= workspaceRegistration == _workspaceRegistration;
            changed |= workspace == _workspace;
            changed |= documentId == _documentId;

            // Now if nothing has changed we're all done!
            if (!changed)
            {
                return(false);
            }

            // OK, so something did change, let's commit the changes.
            //
            // These are all of the straightforward ones.
            _razorBuffer        = razorBuffer;
            _textContainer      = textContainer;
            _isSupportedProject = isSupportedProject;
            _cSharpBuffer       = cSharpBuffer;
            _documentId         = documentId;

            // Now these ones we subscribe to events so it's a little tricky.
            if (_workspaceRegistration != null)
            {
                _workspaceRegistration.WorkspaceChanged -= WorkspaceRegistration_WorkspaceChanged;
            }
            if (workspaceRegistration != null)
            {
                workspaceRegistration.WorkspaceChanged += WorkspaceRegistration_WorkspaceChanged;
            }

            if (_workspace != null)
            {
                _workspace.DocumentActiveContextChanged -= Workspace_DocumentActiveContextChanged;
            }
            if (workspace != null)
            {
                workspace.DocumentActiveContextChanged += Workspace_DocumentActiveContextChanged;
            }

            _workspaceRegistration = workspaceRegistration;
            _workspace             = workspace;

            return(true);
        }
예제 #37
0
        private void SetSubmissionDocument(ITextBuffer buffer, Project project)
        {
            var documentId = DocumentId.CreateNewId(project.Id, debugName: project.Name);
            var solution = project.Solution
                .AddDocument(documentId, project.Name, buffer.CurrentSnapshot.AsText());

            _workspace.SetCurrentSolution(solution);

            // opening document will start workspace listening to changes in this text container
            _workspace.OpenDocument(documentId, buffer.AsTextContainer());
        }
예제 #38
0
 ///<summary>Links an existing <see cref="Document"/> to an <see cref="ITextBuffer"/>, synchronizing their contents.</summary>
 public void OpenDocument(DocumentId documentId, ITextBuffer buffer)
 {
     documentBuffers.Add(documentId, buffer);
     OnDocumentOpened(documentId, buffer.AsTextContainer());
     buffer.Changed += delegate { OnDocumentContextUpdated(documentId); };
 }