internal Task HandleEndBuildAsync(BuildEventArgs args) { if (!args.Success) { // Build failed return(Task.CompletedTask); } return(_projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync((projectItem, ct) => { if (!_projectService.IsSupportedProject(projectItem)) { // We're hooked into all build events, it's possible to get called with an unsupported project item type. return; } var projectPath = _projectService.GetProjectPath(projectItem); var projectSnapshot = _projectManager.GetLoadedProject(projectPath); if (projectSnapshot != null) { var workspaceProject = _projectManager.Workspace.CurrentSolution?.Projects.FirstOrDefault( project => FilePathComparer.Instance.Equals(project.FilePath, projectSnapshot.FilePath)); if (workspaceProject != null) { // Trigger a tag helper update by forcing the project manager to see the workspace Project // from the current solution. _workspaceStateGenerator.Update(workspaceProject, projectSnapshot, CancellationToken.None); } } }, args.SolutionItem, CancellationToken.None)); }
public override ValueTask ProcessAsync(CancellationToken cancellationToken) { var task = _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync( () => _workspaceStateGenerator.Update(_workspaceProject, _projectSnapshot, cancellationToken), cancellationToken); return(new ValueTask(task)); }
// This gets called when the project has finished building. public int UpdateProjectCfg_Done(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, uint dwAction, int fSuccess, int fCancel) { var projectPath = _projectService.GetProjectPath(pHierProj); var projectSnapshot = _projectManager.GetLoadedProject(projectPath); if (projectSnapshot != null) { var workspaceProject = _projectManager.Workspace.CurrentSolution.Projects.FirstOrDefault( wp => FilePathComparer.Instance.Equals(wp.FilePath, projectSnapshot.FilePath)); if (workspaceProject != null) { // Trigger a tag helper update by forcing the project manager to see the workspace Project // from the current solution. _workspaceStateGenerator.Update(workspaceProject, projectSnapshot, CancellationToken.None); } } return(VSConstants.S_OK); }
internal Task OnProjectBuiltAsync(IVsHierarchy projectHierarchy, CancellationToken cancellationToken) { var projectFilePath = _projectService.GetProjectPath(projectHierarchy); return(_projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { var projectSnapshot = _projectManager.GetLoadedProject(projectFilePath); if (projectSnapshot != null) { var workspaceProject = _projectManager.Workspace.CurrentSolution.Projects.FirstOrDefault( wp => FilePathComparer.Instance.Equals(wp.FilePath, projectSnapshot.FilePath)); if (workspaceProject != null) { // Trigger a tag helper update by forcing the project manager to see the workspace Project // from the current solution. _workspaceStateGenerator.Update(workspaceProject, projectSnapshot, cancellationToken); } } }, cancellationToken)); }
private void ExecuteUpdate(object state) { var projectFilePath = SelectedProject?.FilePath; if (projectFilePath == null) { return; } var projectSnapshot = _projectManager.GetLoadedProject(projectFilePath); if (projectSnapshot != null) { var workspaceProject = _workspace.CurrentSolution.Projects.FirstOrDefault( wp => FilePathComparer.Instance.Equals(wp.FilePath, SelectedProject.FilePath)); var solution = _workspace.CurrentSolution; if (workspaceProject != null) { _workspaceStateGenerator.Update(workspaceProject, projectSnapshot); } } }
// Internal for testing internal void ProjectOperations_EndBuild(object sender, BuildEventArgs args) { if (args == null) { throw new ArgumentNullException(nameof(args)); } _foregroundDispatcher.AssertForegroundThread(); if (!args.Success) { // Build failed return; } var projectItem = args.SolutionItem; if (!_projectService.IsSupportedProject(projectItem)) { // We're hooked into all build events, it's possible to get called with an unsupported project item type. return; } var projectPath = _projectService.GetProjectPath(projectItem); var projectSnapshot = _projectManager.GetLoadedProject(projectPath); if (projectSnapshot != null) { var workspaceProject = _projectManager.Workspace.CurrentSolution?.Projects.FirstOrDefault( project => FilePathComparer.Instance.Equals(project.FilePath, projectSnapshot.FilePath)); if (workspaceProject != null) { // Trigger a tag helper update by forcing the project manager to see the workspace Project // from the current solution. _workspaceStateGenerator.Update(workspaceProject, projectSnapshot); } } }
// Internal for testing, virtual for temporary VSCode workaround internal virtual void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e) { Project project; switch (e.Kind) { case WorkspaceChangeKind.ProjectAdded: { project = e.NewSolution.GetProject(e.ProjectId); Debug.Assert(project != null); if (TryGetProjectSnapshot(project.FilePath, out var projectSnapshot)) { _workspaceStateGenerator.Update(project, projectSnapshot); } break; } case WorkspaceChangeKind.ProjectChanged: case WorkspaceChangeKind.ProjectReloaded: { project = e.NewSolution.GetProject(e.ProjectId); if (TryGetProjectSnapshot(project?.FilePath, out var _)) { EnqueueUpdate(e.ProjectId); } break; } case WorkspaceChangeKind.ProjectRemoved: { project = e.OldSolution.GetProject(e.ProjectId); Debug.Assert(project != null); if (TryGetProjectSnapshot(project?.FilePath, out var projectSnapshot)) { _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot); } break; } case WorkspaceChangeKind.DocumentChanged: case WorkspaceChangeKind.DocumentReloaded: { // This is the case when a component declaration file changes on disk. We have an MSBuild // generator configured by the SDK that will poke these files on disk when a component // is saved, or loses focus in the editor. project = e.OldSolution.GetProject(e.ProjectId); var document = project.GetDocument(e.DocumentId); if (document.FilePath == null) { break; } // Using EndsWith because Path.GetExtension will ignore everything before .cs // Using Ordinal because the SDK generates these filenames. if (document.FilePath.EndsWith(".cshtml.g.cs", StringComparison.Ordinal) || document.FilePath.EndsWith(".razor.g.cs", StringComparison.Ordinal)) { EnqueueUpdate(e.ProjectId); } break; } case WorkspaceChangeKind.SolutionAdded: case WorkspaceChangeKind.SolutionChanged: case WorkspaceChangeKind.SolutionCleared: case WorkspaceChangeKind.SolutionReloaded: case WorkspaceChangeKind.SolutionRemoved: if (e.OldSolution != null) { foreach (var p in e.OldSolution.Projects) { if (TryGetProjectSnapshot(p?.FilePath, out var projectSnapshot)) { _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot); } } } InitializeSolution(e.NewSolution); break; } }
// Internal for testing, virtual for temporary VSCode workaround internal virtual void Workspace_WorkspaceChanged(object sender, WorkspaceChangeEventArgs e) { Project project; switch (e.Kind) { case WorkspaceChangeKind.ProjectAdded: { project = e.NewSolution.GetProject(e.ProjectId); Debug.Assert(project != null); if (TryGetProjectSnapshot(project.FilePath, out var projectSnapshot)) { _workspaceStateGenerator.Update(project, projectSnapshot); } break; } case WorkspaceChangeKind.ProjectChanged: case WorkspaceChangeKind.ProjectReloaded: { project = e.NewSolution.GetProject(e.ProjectId); if (TryGetProjectSnapshot(project?.FilePath, out var _)) { EnqueueUpdate(e.ProjectId); } break; } case WorkspaceChangeKind.ProjectRemoved: { project = e.OldSolution.GetProject(e.ProjectId); Debug.Assert(project != null); if (TryGetProjectSnapshot(project?.FilePath, out var projectSnapshot)) { _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot); } break; } case WorkspaceChangeKind.DocumentChanged: case WorkspaceChangeKind.DocumentReloaded: { // This is the case when a component declaration file changes on disk. We have an MSBuild // generator configured by the SDK that will poke these files on disk when a component // is saved, or loses focus in the editor. project = e.OldSolution.GetProject(e.ProjectId); var document = project.GetDocument(e.DocumentId); if (document.FilePath == null) { return; } // Using EndsWith because Path.GetExtension will ignore everything before .cs // Using Ordinal because the SDK generates these filenames. // Stll have .cshtml.g.cs and .razor.g.cs for Razor.VSCode scenarios. if (document.FilePath.EndsWith(".cshtml.g.cs", StringComparison.Ordinal) || document.FilePath.EndsWith(".razor.g.cs", StringComparison.Ordinal) || document.FilePath.EndsWith(".razor", StringComparison.Ordinal) || // VSCode's background C# document document.FilePath.EndsWith("__bg__virtual.cs")) { EnqueueUpdate(e.ProjectId); return; } // We now know we're not operating directly on a Razor file. However, it's possible the user is operating on a partial class that is associated with a Razor file. if (IsPartialComponentClass(document)) { EnqueueUpdate(e.ProjectId); } break; } case WorkspaceChangeKind.SolutionAdded: case WorkspaceChangeKind.SolutionChanged: case WorkspaceChangeKind.SolutionCleared: case WorkspaceChangeKind.SolutionReloaded: case WorkspaceChangeKind.SolutionRemoved: if (e.OldSolution != null) { foreach (var p in e.OldSolution.Projects) { if (TryGetProjectSnapshot(p?.FilePath, out var projectSnapshot)) { _workspaceStateGenerator.Update(workspaceProject: null, projectSnapshot); } } } InitializeSolution(e.NewSolution); break; } }