public bool PasteInto(ModelEntity targetEntity) { return(SourceEntity .Select(source => CopiedTagNames.All(tagName => targetEntity.InsertTaggedValueFrom(source, tagName))) .GetOrElse(false)); }
/// <summary> /// Ensures that <see cref="_currentAggregateProjectContext"/> is updated for the latest TargetFrameworks from the project properties /// and returns this value. /// </summary> private Task <AggregateCrossTargetProjectContext> UpdateProjectContextAsync() { // Ensure that only single thread is attempting to create a project context. AggregateCrossTargetProjectContext previousContextToDispose = null; return(ExecuteWithinLockAsync(async() => { // Check if we have already computed the project context. if (_currentAggregateProjectContext != null) { // For non-cross targeting projects, we can use the current project context if the TargetFramework hasn't changed. // For cross-targeting projects, we need to verify that the current project context matches latest frameworks targeted by the project. // If not, we create a new one and dispose the current one. ConfigurationGeneral projectProperties = await _commonServices.ActiveConfiguredProjectProperties.GetConfigurationGeneralPropertiesAsync().ConfigureAwait(false); if (!_currentAggregateProjectContext.IsCrossTargeting) { ITargetFramework newTargetFramework = _targetFrameworkProvider.GetTargetFramework((string)await projectProperties.TargetFramework.GetValueAsync().ConfigureAwait(false)); if (_currentAggregateProjectContext.ActiveProjectContext.TargetFramework.Equals(newTargetFramework)) { return _currentAggregateProjectContext; } } else { string targetFrameworks = (string)await projectProperties.TargetFrameworks.GetValueAsync().ConfigureAwait(false); // Check if the current project context is up-to-date for the current active and known project configurations. ProjectConfiguration activeProjectConfiguration = _commonServices.ActiveConfiguredProject.ProjectConfiguration; IImmutableSet <ProjectConfiguration> knownProjectConfigurations = await _commonServices.Project.Services.ProjectConfigurationsService.GetKnownProjectConfigurationsAsync().ConfigureAwait(false); if (knownProjectConfigurations.All(c => c.IsCrossTargeting()) && _currentAggregateProjectContext.HasMatchingTargetFrameworks(activeProjectConfiguration, knownProjectConfigurations)) { return _currentAggregateProjectContext; } } previousContextToDispose = _currentAggregateProjectContext; } // Force refresh the CPS active project configuration (needs UI thread). await _commonServices.ThreadingService.SwitchToUIThread(); await _activeProjectConfigurationRefreshService.RefreshActiveProjectConfigurationAsync().ConfigureAwait(false); // Dispose the old project context, if one exists. if (previousContextToDispose != null) { await DisposeAggregateProjectContextAsync(previousContextToDispose).ConfigureAwait(false); } // Create new project context. _currentAggregateProjectContext = await _contextProvider.Value.CreateProjectContextAsync().ConfigureAwait(false); OnAggregateContextChanged(previousContextToDispose, _currentAggregateProjectContext); return _currentAggregateProjectContext; })); }
public Task <CommandStatusResult> GetCommandStatusAsync(IImmutableSet <IProjectTree> items, long commandId, bool focused, string?commandText, CommandStatus progressiveStatus) { if (IsOpenCommand(commandId) && items.All(CanOpenFile)) { progressiveStatus |= CommandStatus.Enabled | CommandStatus.Supported; return(new CommandStatusResult(true, commandText, progressiveStatus).AsTask()); } return(CommandStatusResult.Unhandled.AsTask()); }
protected override Task <CommandStatusResult> GetCommandStatusAsync(IImmutableSet <IProjectTree> nodes, bool focused, string?commandText, CommandStatus progressiveStatus) { // Only handle when Solution Explorer has focus so that we don't take over Tab Well handling if (focused && nodes.All(CanOpen)) { return(GetCommandStatusResult.Handled(commandText, progressiveStatus | CommandStatus.Enabled)); } return(GetCommandStatusResult.Unhandled); }
/// <summary> /// Gets a value indicating whether deleting a given set of items from the project, and optionally from disk, /// would be allowed. /// Note: CanRemove can be called several times since there two types of remove operations: /// - Remove is a command that can remove project tree items form the tree/project but not from disk. /// For that command requests deleteOptions has DeleteOptions.None flag. /// - Delete is a command that can remove project tree items and form project and from disk. /// For this command requests deleteOptions has DeleteOptions.DeleteFromStorage flag. /// We can potentially support only Remove command here, since we don't remove Dependencies form disk, /// thus we return false when DeleteOptions.DeleteFromStorage is provided. /// </summary> /// <param name="nodes">The nodes that should be deleted.</param> /// <param name="deleteOptions"> /// A value indicating whether the items should be deleted from disk as well as from the project file. /// </param> public override bool CanRemove(IImmutableSet <IProjectTree> nodes, DeleteOptions deleteOptions = DeleteOptions.None) { if (deleteOptions.HasFlag(DeleteOptions.DeleteFromStorage)) { return(false); } return(nodes.All(node => node.Flags.Contains(DependencyTreeFlags.SupportsRemove))); }
public override bool CanRemove(IImmutableSet <IProjectTree> nodes, DeleteOptions deleteOptions = DeleteOptions.None) { if (deleteOptions.HasFlag(DeleteOptions.DeleteFromStorage)) { // We support "Remove" but not "Delete". // We remove the dependency from the project, not delete it from disk. return(false); } return(nodes.All(node => node.Flags.Contains(DependencyTreeFlags.SupportsRemove))); }
/// <summary> /// Gets a value indicating whether deleting a given set of items from the project, and optionally from disk, /// would be allowed. /// Note: CanRemove can be called several times since there two types of remove operations: /// - Remove is a command that can remove project tree items form the tree/project but not from disk. /// For that command requests deleteOptions has DeleteOptions.None flag. /// - Delete is a command that can remove project tree items and form project and from disk. /// For this command requests deleteOptions has DeleteOptions.DeleteFromStorage flag. /// We can potentially support only Remove command here, since we don't remove Dependencies form disk, /// thus we return false when DeleteOptions.DeleteFromStorage is provided. /// </summary> /// <param name="nodes">The nodes that should be deleted.</param> /// <param name="deleteOptions"> /// A value indicating whether the items should be deleted from disk as well as from the project file. /// </param> public override bool CanRemove(IImmutableSet <IProjectTree> nodes, DeleteOptions deleteOptions = DeleteOptions.None) { if (deleteOptions.HasFlag(DeleteOptions.DeleteFromStorage)) { return(false); } return(nodes.All(node => (node.Flags.Contains(DependencyNode.GenericDependencyFlags) && node.BrowseObjectProperties != null && !node.Flags.Contains(DependencyNode.DoesNotSupportRemove)))); }
protected override async Task <bool> TryHandleCommandAsync(IImmutableSet <IProjectTree> nodes, bool focused, long commandExecuteOptions, IntPtr variantArgIn, IntPtr variantArgOut) { // Only handle when Solution Explorer has focus so that we don't take over Tab Well handling if (focused && nodes.All(CanOpen)) { foreach (IProjectTree node in nodes) { string?path = await DependencyServices.GetBrowsePathAsync(_project, node); if (path == null) { continue; } Open(path); } return(true); } return(false); }
public Task <bool> TryHandleCommandAsync(IImmutableSet <IProjectTree> items, long commandId, bool focused, long commandExecuteOptions, IntPtr variantArgIn, IntPtr variantArgOut) { if (IsOpenCommand(commandId) && items.All(CanOpenFile)) { OpenItems(); return(TaskResult.True); } return(TaskResult.False); void OpenItems() { Assumes.NotNull(_configuredProject.UnconfiguredProject.Services.HostObject); var hierarchy = (IVsUIHierarchy)_configuredProject.UnconfiguredProject.Services.HostObject; var rdt = new RunningDocumentTable(_serviceProvider); // Open all items. RunAllAndAggregateExceptions(items, OpenItem); void OpenItem(IProjectTree item) { IVsWindowFrame?windowFrame = null; try { // Open the document. Guid logicalView = IsOpenWithCommand(commandId) ? LOGVIEWID_UserChooseView : LOGVIEWID.Primary_guid; IntPtr docData = IntPtr.Zero; ErrorHandler.ThrowOnFailure( _uiShellOpenDocument.Value.OpenStandardEditor( (uint)__VSOSEFLAGS.OSE_ChooseBestStdEditor, item.FilePath, ref logicalView, item.Caption, hierarchy, item.GetHierarchyId(), docData, _oleServiceProvider.Value, out windowFrame)); RunningDocumentInfo rdtInfo = rdt.GetDocumentInfo(item.FilePath); // Set it as read only if necessary. bool isReadOnly = item.Flags.Contains(ImportTreeProvider.ProjectImportImplicit); if (isReadOnly && rdtInfo.DocData is IVsTextBuffer textBuffer) { textBuffer.GetStateFlags(out uint flags); textBuffer.SetStateFlags(flags | (uint)BUFFERSTATEFLAGS.BSF_USER_READONLY); } // Detach the document from this project. // Ignore failure. It may be that we've already transferred the item to Miscellaneous Files. _externalFilesManager.Value.TransferDocument(item.FilePath, item.FilePath, windowFrame); // Show the document window if (windowFrame != null) { ErrorHandler.ThrowOnFailure(windowFrame.Show()); } } catch { windowFrame?.CloseFrame(0); throw; } } } }
/// <summary> /// Determines whether the current project context object is out of date based on the project's target frameworks. /// If so, a new one is created and subscriptions are updated accordingly. /// </summary> private async Task UpdateProjectContextAndSubscriptionsAsync() { // Ensure that only single thread is attempting to create a project context. AggregateCrossTargetProjectContext newProjectContext = await ExecuteWithinLockAsync(TryUpdateCurrentAggregateProjectContextAsync); if (newProjectContext != null) { // Dispose existing subscriptions. DisposeAndClearSubscriptions(); // Add subscriptions for the configured projects in the new project context. await AddSubscriptionsAsync(newProjectContext); } return; async Task <AggregateCrossTargetProjectContext> TryUpdateCurrentAggregateProjectContextAsync() { AggregateCrossTargetProjectContext previousContext = _currentAggregateProjectContext; // Check if we have already computed the project context. if (previousContext != null) { // For non-cross targeting projects, we can use the current project context if the TargetFramework hasn't changed. // For cross-targeting projects, we need to verify that the current project context matches latest frameworks targeted by the project. // If not, we create a new one and dispose the current one. ConfigurationGeneral projectProperties = await _commonServices.ActiveConfiguredProjectProperties.GetConfigurationGeneralPropertiesAsync(); if (!previousContext.IsCrossTargeting) { string newTargetFrameworkName = (string)await projectProperties.TargetFramework.GetValueAsync(); ITargetFramework newTargetFramework = _targetFrameworkProvider.GetTargetFramework(newTargetFrameworkName); if (previousContext.ActiveTargetFramework.Equals(newTargetFramework)) { // No change return(null); } } else { // Check if the current project context is up-to-date for the current active and known project configurations. ProjectConfiguration activeProjectConfiguration = _commonServices.ActiveConfiguredProject.ProjectConfiguration; IImmutableSet <ProjectConfiguration> knownProjectConfigurations = await _commonServices.Project.Services.ProjectConfigurationsService.GetKnownProjectConfigurationsAsync(); if (knownProjectConfigurations.All(c => c.IsCrossTargeting()) && HasMatchingTargetFrameworks(previousContext, activeProjectConfiguration, knownProjectConfigurations)) { // No change return(null); } } } // Force refresh the CPS active project configuration (needs UI thread). await _commonServices.ThreadingService.SwitchToUIThread(); await _activeProjectConfigurationRefreshService.RefreshActiveProjectConfigurationAsync(); // Create new project context. AggregateCrossTargetProjectContext newContext = await _contextProvider.Value.CreateProjectContextAsync(); _currentAggregateProjectContext = newContext; OnAggregateContextChanged(previousContext, newContext); return(newContext); } bool HasMatchingTargetFrameworks( AggregateCrossTargetProjectContext previousContext, ProjectConfiguration activeProjectConfiguration, IReadOnlyCollection <ProjectConfiguration> knownProjectConfigurations) { Assumes.True(activeProjectConfiguration.IsCrossTargeting()); ITargetFramework activeTargetFramework = _targetFrameworkProvider.GetTargetFramework(activeProjectConfiguration.Dimensions[ConfigurationGeneral.TargetFrameworkProperty]); if (!previousContext.ActiveTargetFramework.Equals(activeTargetFramework)) { // Active target framework is different. return(false); } var targetFrameworkMonikers = knownProjectConfigurations .Select(c => c.Dimensions[ConfigurationGeneral.TargetFrameworkProperty]) .Distinct() .ToList(); if (targetFrameworkMonikers.Count != previousContext.TargetFrameworks.Length) { // Different number of target frameworks. return(false); } foreach (string targetFrameworkMoniker in targetFrameworkMonikers) { ITargetFramework targetFramework = _targetFrameworkProvider.GetTargetFramework(targetFrameworkMoniker); if (!previousContext.TargetFrameworks.Contains(targetFramework)) { // Differing TargetFramework return(false); } } return(true); } void OnAggregateContextChanged( AggregateCrossTargetProjectContext oldContext, AggregateCrossTargetProjectContext newContext) { if (oldContext == null) { // all new rules will be sent to new context, we don't need to clean up anything return; } var targetsToClean = new HashSet <ITargetFramework>(); ImmutableArray <ITargetFramework> oldTargets = oldContext.TargetFrameworks; if (newContext == null) { targetsToClean.AddRange(oldTargets); } else { ImmutableArray <ITargetFramework> newTargets = newContext.TargetFrameworks; targetsToClean.AddRange(oldTargets.Except(newTargets)); } if (targetsToClean.Count != 0) { TryUpdateSnapshot(snapshot => snapshot.RemoveTargets(targetsToClean)); } } }
public async Task <AggregateCrossTargetProjectContext?> TryUpdateCurrentAggregateProjectContextAsync() { AggregateCrossTargetProjectContext?previousContext = Current; // Check if we have already computed the project context. if (previousContext != null) { // For non-cross targeting projects, we can use the current project context if the TargetFramework hasn't changed. // For cross-targeting projects, we need to verify that the current project context matches latest frameworks targeted by the project. // If not, we create a new one and dispose the current one. ConfigurationGeneral projectProperties = await _commonServices.ActiveConfiguredProjectProperties.GetConfigurationGeneralPropertiesAsync(); if (!previousContext.IsCrossTargeting) { string?newTargetFrameworkName = (string?)await projectProperties.TargetFrameworkMoniker.GetValueAsync(); if (string.IsNullOrEmpty(newTargetFrameworkName) && TargetFramework.Empty.Equals(previousContext.ActiveTargetFramework)) { // No change return(null); } TargetFramework?newTargetFramework = _targetFrameworkProvider.GetTargetFramework(newTargetFrameworkName); if (previousContext.ActiveTargetFramework.Equals(newTargetFramework)) { // No change return(null); } } else { // Check if the current project context is up-to-date for the current active and known project configurations. Assumes.Present(_commonServices.Project.Services.ProjectConfigurationsService); ProjectConfiguration activeProjectConfiguration = _commonServices.ActiveConfiguredProject.ProjectConfiguration; IImmutableSet <ProjectConfiguration> knownProjectConfigurations = await _commonServices.Project.Services.ProjectConfigurationsService.GetKnownProjectConfigurationsAsync(); if (knownProjectConfigurations.All(c => c.IsCrossTargeting()) && HasMatchingTargetFrameworks(activeProjectConfiguration, knownProjectConfigurations)) { // No change return(null); } } } // Force refresh the CPS active project configuration (needs UI thread). await _commonServices.ThreadingService.SwitchToUIThread(); await _activeProjectConfigurationRefreshService.RefreshActiveProjectConfigurationAsync(); // Create new project context. AggregateCrossTargetProjectContext newContext = await _contextProvider.Value.CreateProjectContextAsync(); Current = newContext; return(newContext); bool HasMatchingTargetFrameworks( ProjectConfiguration activeProjectConfiguration, IReadOnlyCollection <ProjectConfiguration> knownProjectConfigurations) { Assumes.NotNull(previousContext); Assumes.True(activeProjectConfiguration.IsCrossTargeting()); TargetFramework?activeTargetFramework = _targetFrameworkProvider.GetTargetFramework(activeProjectConfiguration.Dimensions[ConfigurationGeneral.TargetFrameworkProperty]); if (!previousContext.ActiveTargetFramework.Equals(activeTargetFramework)) { // Active target framework is different. return(false); } var targetFrameworkMonikers = knownProjectConfigurations .Select(c => c.Dimensions[ConfigurationGeneral.TargetFrameworkProperty]) .Distinct() .ToList(); if (targetFrameworkMonikers.Count != previousContext.TargetFrameworks.Length) { // Different number of target frameworks. return(false); } foreach (string targetFrameworkMoniker in targetFrameworkMonikers) { TargetFramework?targetFramework = _targetFrameworkProvider.GetTargetFramework(targetFrameworkMoniker); if (targetFramework == null || !previousContext.TargetFrameworks.Contains(targetFramework)) { // Differing TargetFramework return(false); } } return(true); } }