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); } }
/// <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; }
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); } }
///<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; }
///<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; }
///<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); }
/// <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); } }
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); } } }
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); }
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); } } } }
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()); }
internal static bool TryGetWorkspace(this ITextBuffer buffer, out Workspace workspace) => Workspace.TryGetWorkspace(buffer.AsTextContainer(), out workspace);
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; }
///<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); }; }
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)); }
/// <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); }
internal static bool CanApplyChangeDocumentToWorkspace(this ITextBuffer buffer) => Workspace.TryGetWorkspace(buffer.AsTextContainer(), out var workspace) && workspace.CanApplyChange(ApplyChangesKind.ChangeDocument);
///<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); }
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()); }
/// <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); }
internal static bool TryGetWorkspace(this ITextBuffer buffer, [NotNullWhen(true)] out Workspace?workspace) => Workspace.TryGetWorkspace(buffer.AsTextContainer(), out workspace);
SourceTextContainer ISourceTextHelper.AsTextContainer(ITextBuffer buffer) => buffer.AsTextContainer();
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; } }
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); }
public SourceTextContainer GetOpenTextContainer() { return(_openTextBuffer.AsTextContainer()); }
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; } }
void IVisualStudioWorkspaceHost.OnAdditionalDocumentOpened(DocumentId documentId, ITextBuffer textBuffer, bool isCurrentContext) { _workspace.OnAdditionalDocumentOpened(documentId, textBuffer.AsTextContainer(), isCurrentContext); }
/// <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();
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); }
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()); }