diff --git a/src/BuildVision.Contracts/BuildVision.Contracts.csproj b/src/BuildVision.Contracts/BuildVision.Contracts.csproj index 37f38f4b..e1ae6667 100644 --- a/src/BuildVision.Contracts/BuildVision.Contracts.csproj +++ b/src/BuildVision.Contracts/BuildVision.Contracts.csproj @@ -61,6 +61,8 @@ <Compile Include="Enums\ErrorLevel.cs" /> <Compile Include="ErrorsBox.cs" /> <Compile Include="Enums\ProjectState.cs" /> + <Compile Include="Models\IBuildInformationModel.cs" /> + <Compile Include="Models\ISolutionModel.cs" /> <Compile Include="ProjectNotFoundException.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="PropertyNotFoundException.cs" /> diff --git a/src/BuildVision.Contracts/Enums/BuildActions.cs b/src/BuildVision.Contracts/Enums/BuildActions.cs index 943ab442..61ef61be 100644 --- a/src/BuildVision.Contracts/Enums/BuildActions.cs +++ b/src/BuildVision.Contracts/Enums/BuildActions.cs @@ -11,6 +11,7 @@ public enum BuildActions BuildActionBuild = 1, BuildActionRebuildAll = 2, BuildActionClean = 3, - BuildActionDeploy = 4 + BuildActionDeploy = 4, + Unknown = 5 } } diff --git a/src/BuildVision.Contracts/Enums/BuildScopes.cs b/src/BuildVision.Contracts/Enums/BuildScopes.cs index 304f2bc8..416b1f00 100644 --- a/src/BuildVision.Contracts/Enums/BuildScopes.cs +++ b/src/BuildVision.Contracts/Enums/BuildScopes.cs @@ -4,6 +4,7 @@ public enum BuildScopes { BuildScopeSolution = 1, BuildScopeBatch = 2, - BuildScopeProject = 3 + BuildScopeProject = 3, + Unknown = 4 } } diff --git a/src/BuildVision.Contracts/Enums/BuildState.cs b/src/BuildVision.Contracts/Enums/BuildState.cs index 9d58869c..5d1e91d7 100644 --- a/src/BuildVision.Contracts/Enums/BuildState.cs +++ b/src/BuildVision.Contracts/Enums/BuildState.cs @@ -5,6 +5,7 @@ public enum BuildState NotStarted = 0, InProgress = 1, Done = 2, - Cancelled = 3 + Cancelled = 3, + Failed = 4 } } diff --git a/src/BuildVision.Contracts/Models/IBuildInformationModel.cs b/src/BuildVision.Contracts/Models/IBuildInformationModel.cs new file mode 100644 index 00000000..fbe28403 --- /dev/null +++ b/src/BuildVision.Contracts/Models/IBuildInformationModel.cs @@ -0,0 +1,24 @@ +using System; + +namespace BuildVision.Contracts.Models +{ + public interface IBuildInformationModel + { + BuildActions BuildAction { get; set; } + DateTime? BuildFinishTime { get; set; } + BuildScopes BuildScope { get; set; } + DateTime? BuildStartTime { get; set; } + BuildState CurrentBuildState { get; set; } + int ErrorCount { get; set; } + int FailedProjectsCount { get; set; } + int MessagesCount { get; set; } + BuildResultState ResultState { get; } + string StateMessage { get; set; } + int SucceededProjectsCount { get; set; } + int UpToDateProjectsCount { get; set; } + int WarnedProjectsCount { get; set; } + int WarningsCount { get; set; } + + BuildResultState GetBuildState(); + } +} diff --git a/src/BuildVision.Contracts/Models/ISolutionModel.cs b/src/BuildVision.Contracts/Models/ISolutionModel.cs new file mode 100644 index 00000000..3eb65d4d --- /dev/null +++ b/src/BuildVision.Contracts/Models/ISolutionModel.cs @@ -0,0 +1,10 @@ +namespace BuildVision.Contracts.Models +{ + public interface ISolutionModel + { + string FileName { get; set; } + string FullName { get; set; } + bool IsEmpty { get; set; } + string Name { get; set; } + } +} diff --git a/src/BuildVision.Exports/BuildVision.Exports.csproj b/src/BuildVision.Exports/BuildVision.Exports.csproj index 2095a5ba..bf5367fa 100644 --- a/src/BuildVision.Exports/BuildVision.Exports.csproj +++ b/src/BuildVision.Exports/BuildVision.Exports.csproj @@ -6,4 +6,8 @@ <AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile> </PropertyGroup> + <ItemGroup> + <ProjectReference Include="..\BuildVision.Contracts\BuildVision.Contracts.csproj" /> + </ItemGroup> + </Project> diff --git a/src/BuildVision.Exports/Providers/IBuildInformationProvider.cs b/src/BuildVision.Exports/Providers/IBuildInformationProvider.cs new file mode 100644 index 00000000..0210b8c0 --- /dev/null +++ b/src/BuildVision.Exports/Providers/IBuildInformationProvider.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using BuildVision.Contracts.Models; + +namespace BuildVision.Exports.Providers +{ + public interface IBuildInformationProvider + { + void BuildFinished(bool success, bool modified, bool canceled); + void BuildStarted(uint dwAction); + void BuildUpdate(); + IBuildInformationModel GetBuildInformationModel(); + } +} diff --git a/src/BuildVision.UI/Helpers/DisplayStringAttribute.cs b/src/BuildVision.UI/Attributes/DisplayStringAttribute.cs similarity index 100% rename from src/BuildVision.UI/Helpers/DisplayStringAttribute.cs rename to src/BuildVision.UI/Attributes/DisplayStringAttribute.cs diff --git a/src/BuildVision.UI/Models/GridColumnAttribute.cs b/src/BuildVision.UI/Attributes/GridColumnAttribute.cs similarity index 100% rename from src/BuildVision.UI/Models/GridColumnAttribute.cs rename to src/BuildVision.UI/Attributes/GridColumnAttribute.cs diff --git a/src/BuildVision.UI/BuildVision.UI.csproj b/src/BuildVision.UI/BuildVision.UI.csproj index 12b18850..a69c589f 100644 --- a/src/BuildVision.UI/BuildVision.UI.csproj +++ b/src/BuildVision.UI/BuildVision.UI.csproj @@ -73,15 +73,15 @@ <DependentUpon>App.xaml</DependentUpon> <SubType>Code</SubType> </Compile> - <Compile Include="Helpers\ResetTaskBarItemInfoCondition.cs" /> + <Compile Include="Enums\ResetTaskBarItemInfoCondition.cs" /> <Compile Include="Helpers\SortDescription.cs" /> - <Compile Include="Helpers\SortOrder.cs" /> - <Compile Include="Helpers\WindowState.cs" /> + <Compile Include="Enums\SortOrder.cs" /> + <Compile Include="Enums\WindowState.cs" /> <Compile Include="Helpers\WindowStateAction.cs" /> <Compile Include="IPackageSettingsProvider.cs" /> - <Compile Include="Models\BaseGridColumnSettings.cs" /> - <Compile Include="Models\BuildMessagesSettings.cs" /> - <Compile Include="Models\BuildProgressSettings.cs" /> + <Compile Include="Settings\Models\BaseGridColumnSettings.cs" /> + <Compile Include="Settings\Models\BuildMessagesSettings.cs" /> + <Compile Include="Settings\Models\BuildProgressSettings.cs" /> <Compile Include="Common\Logging\BindingErrorListener.cs" /> <Compile Include="Common\Logging\TraceManager.cs" /> <Compile Include="Components\ControlHeader.xaml.cs"> @@ -92,13 +92,13 @@ </Compile> <Compile Include="Contracts\BuildedProjectsCollection.cs" /> <Compile Include="Contracts\BuildProjectContextEntry.cs" /> - <Compile Include="Models\ControlSettings.cs" /> - <Compile Include="Models\GeneralSettings.cs" /> - <Compile Include="Models\GridColumnSettings.cs" /> + <Compile Include="Settings\Models\ControlSettings.cs" /> + <Compile Include="Settings\Models\GeneralSettings.cs" /> + <Compile Include="Settings\Models\GridColumnSettings.cs" /> <Compile Include="Models\GridColumnSettingsCollection.cs" /> - <Compile Include="Models\GridSettings.cs" /> + <Compile Include="Settings\Models\GridSettings.cs" /> <Compile Include="Helpers\BindingProxy.cs" /> - <Compile Include="Helpers\BuildMessages.cs" /> + <Compile Include="Helpers\BuildMessagesFactory.cs" /> <Compile Include="Contracts\BuildProjectEventArgs.cs" /> <Compile Include="Components\ControlView.xaml.cs"> <DependentUpon>ControlView.xaml</DependentUpon> @@ -115,7 +115,7 @@ <Compile Include="Extensions\TextBlockUtils.cs" /> <Compile Include="Extensions\VectorResources.cs" /> <Compile Include="Extensions\VisualHelper.cs" /> - <Compile Include="Helpers\DisplayStringAttribute.cs" /> + <Compile Include="Attributes\DisplayStringAttribute.cs" /> <Compile Include="Helpers\EnumExtensions.cs" /> <Compile Include="Helpers\StyleConverting.cs" /> <Compile Include="MainWindow.xaml.cs"> @@ -123,13 +123,12 @@ </Compile> <Compile Include="Models\ProjectItem.cs" /> <Compile Include="Extensions\ProjectStateExtensions.cs" /> - <Compile Include="Models\BuildExtraMessageFormat.cs" /> - <Compile Include="Models\BuildMajorMessageFormat.cs" /> - <Compile Include="Models\NavigateToBuildFailureReasonCondition.cs" /> - <Compile Include="Models\GridColumnAttribute.cs" /> + <Compile Include="Enums\BuildExtraMessageFormat.cs" /> + <Compile Include="Enums\BuildMajorMessageFormat.cs" /> + <Compile Include="Enums\NavigateToBuildFailureReasonCondition.cs" /> + <Compile Include="Attributes\GridColumnAttribute.cs" /> <Compile Include="Helpers\ProjectItemColumnSorter.cs" /> - <Compile Include="Models\SolutionItem.cs" /> - <Compile Include="Models\ProjectItemSettings.cs" /> + <Compile Include="Settings\Models\ProjectItemSettings.cs" /> <Compile Include="Resources.Designer.cs"> <DependentUpon>Resources.resx</DependentUpon> <AutoGen>True</AutoGen> @@ -153,11 +152,11 @@ <Compile Include="Settings\WindowSettingsControl.xaml.cs"> <DependentUpon>WindowSettingsControl.xaml</DependentUpon> </Compile> - <Compile Include="ViewModels\SolutionModel.cs" /> + <Compile Include="Models\BuildInformationModel.cs" /> + <Compile Include="Models\SolutionModel.cs" /> <Compile Include="ViewModels\BuildProgressViewModel.cs" /> <Compile Include="ViewModels\BuildVisionPaneViewModel.cs" /> - <Compile Include="ViewModels\VisualStudioSolution.cs" /> - <Compile Include="Models\WindowSettings.cs" /> + <Compile Include="Settings\Models\WindowSettings.cs" /> </ItemGroup> <ItemGroup> <Compile Include="Converters\AlternatingRowBackgroundConverter.cs" /> diff --git a/src/BuildVision.UI/Components/ControlHeader.xaml b/src/BuildVision.UI/Components/ControlHeader.xaml index bde829d0..c12648b8 100644 --- a/src/BuildVision.UI/Components/ControlHeader.xaml +++ b/src/BuildVision.UI/Components/ControlHeader.xaml @@ -4,8 +4,8 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" - xmlns:dvm="clr-namespace:BuildVision.UI.ViewModels" - d:DataContext ="{d:DesignInstance {x:Type dvm:BuildMetaInformationsViewModel}, IsDesignTimeCreatable=True}" + xmlns:dvm="clr-namespace:BuildVision.Contracts.Models" + d:DataContext ="{d:DesignInstance {x:Type dvm:IBuildInformationModel}, IsDesignTimeCreatable=True}" d:DesignWidth="697" xmlns:res="clr-namespace:BuildVision.UI" xmlns:extensions1="clr-namespace:BuildVision.UI.Extensions" diff --git a/src/BuildVision.UI/Components/ControlView.xaml b/src/BuildVision.UI/Components/ControlView.xaml index 17759e95..04cf0d81 100644 --- a/src/BuildVision.UI/Components/ControlView.xaml +++ b/src/BuildVision.UI/Components/ControlView.xaml @@ -101,7 +101,7 @@ <RowDefinition Height="*" /> </Grid.RowDefinitions> - <components:ControlHeader DataContext="{Binding}" + <components:ControlHeader DataContext="{Binding BuildInformationModel}" Grid.Row="0" Height="auto" /> @@ -345,4 +345,4 @@ </DataGrid.RowDetailsTemplate> </DataGrid> </Grid> -</UserControl> \ No newline at end of file +</UserControl> diff --git a/src/BuildVision.UI/Models/BuildExtraMessageFormat.cs b/src/BuildVision.UI/Enums/BuildExtraMessageFormat.cs similarity index 100% rename from src/BuildVision.UI/Models/BuildExtraMessageFormat.cs rename to src/BuildVision.UI/Enums/BuildExtraMessageFormat.cs diff --git a/src/BuildVision.UI/Models/BuildMajorMessageFormat.cs b/src/BuildVision.UI/Enums/BuildMajorMessageFormat.cs similarity index 100% rename from src/BuildVision.UI/Models/BuildMajorMessageFormat.cs rename to src/BuildVision.UI/Enums/BuildMajorMessageFormat.cs diff --git a/src/BuildVision.UI/Models/NavigateToBuildFailureReasonCondition.cs b/src/BuildVision.UI/Enums/NavigateToBuildFailureReasonCondition.cs similarity index 100% rename from src/BuildVision.UI/Models/NavigateToBuildFailureReasonCondition.cs rename to src/BuildVision.UI/Enums/NavigateToBuildFailureReasonCondition.cs diff --git a/src/BuildVision.UI/Helpers/ResetTaskBarItemInfoCondition.cs b/src/BuildVision.UI/Enums/ResetTaskBarItemInfoCondition.cs similarity index 100% rename from src/BuildVision.UI/Helpers/ResetTaskBarItemInfoCondition.cs rename to src/BuildVision.UI/Enums/ResetTaskBarItemInfoCondition.cs diff --git a/src/BuildVision.UI/Helpers/SortOrder.cs b/src/BuildVision.UI/Enums/SortOrder.cs similarity index 100% rename from src/BuildVision.UI/Helpers/SortOrder.cs rename to src/BuildVision.UI/Enums/SortOrder.cs diff --git a/src/BuildVision.UI/Helpers/WindowState.cs b/src/BuildVision.UI/Enums/WindowState.cs similarity index 100% rename from src/BuildVision.UI/Helpers/WindowState.cs rename to src/BuildVision.UI/Enums/WindowState.cs diff --git a/src/BuildVision.UI/Helpers/BindingProxy.cs b/src/BuildVision.UI/Helpers/BindingProxy.cs index 53e57663..652e08e8 100644 --- a/src/BuildVision.UI/Helpers/BindingProxy.cs +++ b/src/BuildVision.UI/Helpers/BindingProxy.cs @@ -15,7 +15,7 @@ protected override Freezable CreateInstanceCore() public object Data { - get { return (object)GetValue(DataProperty); } + get { return (object) GetValue(DataProperty); } set { SetValue(DataProperty, value); } } diff --git a/src/BuildVision.UI/Helpers/BuildMessages.cs b/src/BuildVision.UI/Helpers/BuildMessagesFactory.cs similarity index 75% rename from src/BuildVision.UI/Helpers/BuildMessages.cs rename to src/BuildVision.UI/Helpers/BuildMessagesFactory.cs index d5311c14..ca2e5b4e 100644 --- a/src/BuildVision.UI/Helpers/BuildMessages.cs +++ b/src/BuildVision.UI/Helpers/BuildMessagesFactory.cs @@ -16,20 +16,20 @@ public BuildMessagesFactory(BuildMessagesSettings labelsSettings) _labelSettings = labelsSettings; } - public string GetBuildBeginMajorMessage(VisualStudioSolution solutionItem) + public string GetBuildBeginMajorMessage(SolutionModel solutionItem, BuildInformationModel buildInformationModel) { - var mainString = GetMainString(solutionItem); + var mainString = GetMainString(solutionItem, buildInformationModel); return string.Format(_labelSettings.BuildBeginMajorMessageStringFormat, mainString); } - private string GetMainString(VisualStudioSolution solutionItem) + private string GetMainString(SolutionModel solutionItem, BuildInformationModel buildInformationModel) { var buildAction = BuildActions.BuildActionBuild; //TOdo replace - var unitName = GetUnitName(solutionItem); - var actionName = GetActionName(solutionItem.BuildAction); - var beginAtString = GetBeginAtString(solutionItem.BuildAction); - var timeString = GetTimeString(solutionItem); + var unitName = GetUnitName(solutionItem, buildInformationModel); + var actionName = GetActionName(buildInformationModel.BuildAction); + var beginAtString = GetBeginAtString(buildInformationModel.BuildAction); + var timeString = GetTimeString(solutionItem, buildInformationModel); string mainString; switch (_labelSettings.MajorMessageFormat) { @@ -48,12 +48,12 @@ private string GetMainString(VisualStudioSolution solutionItem) return mainString; } - private string GetTimeString(VisualStudioSolution solution) + private string GetTimeString(SolutionModel solution, BuildInformationModel buildInformationModel) { string timeString = ""; try { - timeString = solution.BuildStartTime.Value.ToString(_labelSettings.DateTimeFormat); + timeString = buildInformationModel.BuildStartTime.Value.ToString(_labelSettings.DateTimeFormat); } catch (FormatException) { @@ -97,10 +97,10 @@ private string GetActionName(BuildActions buildAction) } } - private string GetUnitName(VisualStudioSolution solutionItem) + private string GetUnitName(SolutionModel solutionItem, BuildInformationModel buildInformationModel) { string unitName = ""; - switch (solutionItem.BuildScope) + switch (buildInformationModel.BuildScope) { case BuildScopes.BuildScopeSolution: unitName = Resources.BuildScopeSolution_UnitName; @@ -118,20 +118,20 @@ private string GetUnitName(VisualStudioSolution solutionItem) break; default: - throw new ArgumentOutOfRangeException(nameof(solutionItem.BuildScope)); + throw new ArgumentOutOfRangeException(nameof(buildInformationModel.BuildScope)); } return unitName; } - public string GetBuildBeginExtraMessage(VisualStudioSolution solutionItem) + public string GetBuildBeginExtraMessage(SolutionModel solutionItem, BuildInformationModel buildInformationModel) { - if (solutionItem.BuildStartTime == null || !_labelSettings.ShowExtraMessage || _labelSettings.ExtraMessageDelay < 0) + if (buildInformationModel.BuildStartTime == null || !_labelSettings.ShowExtraMessage || _labelSettings.ExtraMessageDelay < 0) { return string.Empty; } - TimeSpan timeSpan = DateTime.Now.Subtract(solutionItem.BuildStartTime.Value); + TimeSpan timeSpan = DateTime.Now.Subtract(buildInformationModel.BuildStartTime.Value); if (timeSpan.TotalSeconds > _labelSettings.ExtraMessageDelay) { return GetExtraTimePartString( timeSpan); @@ -140,23 +140,23 @@ public string GetBuildBeginExtraMessage(VisualStudioSolution solutionItem) return string.Empty; } - public string GetBuildDoneMessage(VisualStudioSolution solutionItem) + public string GetBuildDoneMessage(SolutionModel solutionItem, BuildInformationModel buildInformationModel) { - return GetBuildDoneMajorMessage(solutionItem) + GetBuildDoneExtraMessage(solutionItem); + return GetBuildDoneMajorMessage(solutionItem, buildInformationModel) + GetBuildDoneExtraMessage(solutionItem, buildInformationModel); } - private string GetBuildDoneMajorMessage(VisualStudioSolution solutionItem) + private string GetBuildDoneMajorMessage(SolutionModel solutionItem, BuildInformationModel buildInformationModel) { - var buildAction = solutionItem.BuildAction; - var buildScope = solutionItem.BuildScope; + var buildAction = buildInformationModel.BuildAction; + var buildScope = buildInformationModel.BuildScope; - if (solutionItem.BuildFinishTime == null) + if (buildInformationModel.BuildFinishTime == null) throw new InvalidOperationException(); string timeString; try { - timeString = solutionItem.BuildFinishTime.Value.ToString(_labelSettings.DateTimeFormat); + timeString = buildInformationModel.BuildFinishTime.Value.ToString(_labelSettings.DateTimeFormat); } catch (FormatException) { @@ -181,9 +181,9 @@ private string GetBuildDoneMajorMessage(VisualStudioSolution solutionItem) if (_labelSettings.ShowProjectName) { // Todo this is probably wrong. maybe we should go the extra mile and check which projects are selected? - var uniqProjName = solutionItem.Projects.LastOrDefault(x => x.State == ProjectState.BuildDone)?.UniqueName; - var projItem = solutionItem.Projects.FirstOrDefault(item => item.UniqueName == uniqProjName); - unitName += string.Format(Resources.BuildScopeProject_ProjectNameTemplate, projItem.Name); + //var uniqProjName = solutionItem.Projects.LastOrDefault(x => x.State == ProjectState.BuildDone)?.UniqueName; + //var projItem = solutionItem.Projects.FirstOrDefault(item => item.UniqueName == uniqProjName); + //unitName += string.Format(Resources.BuildScopeProject_ProjectNameTemplate, projItem.Name); } break; @@ -191,8 +191,8 @@ private string GetBuildDoneMajorMessage(VisualStudioSolution solutionItem) throw new ArgumentOutOfRangeException(nameof(buildScope)); } - var actionName = GetActionName(solutionItem.BuildAction); - var resultName = GetResultName(solutionItem.ResultState); + var actionName = GetActionName(buildInformationModel.BuildAction); + var resultName = GetResultName(buildInformationModel.ResultState); string mainString; switch (_labelSettings.MajorMessageFormat) @@ -239,12 +239,12 @@ private string GetResultName(BuildResultState resultState) } } - private string GetBuildDoneExtraMessage(VisualStudioSolution solutionItem) + private string GetBuildDoneExtraMessage(SolutionModel solutionItem, BuildInformationModel buildInformationModel) { - if (solutionItem.BuildStartTime == null || solutionItem.BuildFinishTime == null || !_labelSettings.ShowExtraMessage) + if (buildInformationModel.BuildStartTime == null || buildInformationModel.BuildFinishTime == null || !_labelSettings.ShowExtraMessage) return string.Empty; - TimeSpan timeSpan = solutionItem.BuildFinishTime.Value.Subtract(solutionItem.BuildStartTime.Value); + TimeSpan timeSpan = buildInformationModel.BuildFinishTime.Value.Subtract(buildInformationModel.BuildStartTime.Value); string extraTimePartString = GetExtraTimePartString(timeSpan); return string.Format(_labelSettings.ExtraMessageStringFormat, extraTimePartString); } diff --git a/src/BuildVision.UI/Models/BaseGridColumnSettings.cs b/src/BuildVision.UI/Models/BaseGridColumnSettings.cs deleted file mode 100644 index 81e58925..00000000 --- a/src/BuildVision.UI/Models/BaseGridColumnSettings.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace BuildVision.Contracts -{ - public abstract class BaseGridColumnSettingsAttribute : Attribute - { - public string Header { get; set; } - - public bool Visible { get; set; } - - /// <remarks> - /// -1 for auto. - /// </remarks> - public int DisplayIndex { get; set; } - - /// <remarks> - /// double.NaN for auto. - /// </remarks> - public double Width { get; set; } - - public string ValueStringFormat { get; set; } - - protected BaseGridColumnSettingsAttribute() - { - Width = double.NaN; - DisplayIndex = -1; - Visible = true; - } - } -} diff --git a/src/BuildVision.UI/Models/BuildInformationModel.cs b/src/BuildVision.UI/Models/BuildInformationModel.cs new file mode 100644 index 00000000..7a1967b1 --- /dev/null +++ b/src/BuildVision.UI/Models/BuildInformationModel.cs @@ -0,0 +1,154 @@ +using System; +using BuildVision.Common; +using BuildVision.Contracts; +using BuildVision.Contracts.Models; + +namespace BuildVision.Core +{ + public class BuildInformationModel : BindableBase, IBuildInformationModel + { + private int _errorCount = -1; + public int ErrorCount + { + get => _errorCount; + set => SetProperty(ref _errorCount, value); + } + + private int _warningsCount = -1; + public int WarningsCount + { + get => _warningsCount; + set => SetProperty(ref _warningsCount, value); + } + + private int _messagesCount = -1; + public int MessagesCount + { + get => _messagesCount; + set => SetProperty(ref _messagesCount, value); + } + + private int _succeededProjectsCount = -1; + public int SucceededProjectsCount + { + get => _warningsCount; + set => SetProperty(ref _succeededProjectsCount, value); + } + + private int _upToDateProjectsCount = -1; + public int UpToDateProjectsCount + { + get => _warningsCount; + set => SetProperty(ref _upToDateProjectsCount, value); + } + + private int _failedProjectsCount = -1; + public int FailedProjectsCount + { + get => _warningsCount; + set => SetProperty(ref _failedProjectsCount, value); + } + + private int _warnedProjectsCount = -1; + public int WarnedProjectsCount + { + get => _warningsCount; + set => SetProperty(ref _warnedProjectsCount, value); + } + + private string _stateMessage = ""; + public string StateMessage + { + get => _stateMessage; + set => SetProperty(ref _stateMessage, value); + } + + private BuildState _currentBuildState = BuildState.NotStarted; + public BuildState CurrentBuildState + { + get => _currentBuildState; + set => SetProperty(ref _currentBuildState, value); + } + + public BuildResultState ResultState => GetBuildState(); + + private BuildActions _buildAction = BuildActions.Unknown; + public BuildActions BuildAction + { + get => _buildAction; + set => SetProperty(ref _buildAction, value); + } + + private BuildScopes _buildScope = BuildScopes.Unknown; + public BuildScopes BuildScope + { + get => _buildScope; + set => SetProperty(ref _buildScope, value); + } + + private DateTime? _buildStartTime; + public DateTime? BuildStartTime + { + get => _buildStartTime; + set => SetProperty(ref _buildStartTime, value); + } + + private DateTime? _buildFinishTime; + public DateTime? BuildFinishTime + { + get => _buildFinishTime; + set => SetProperty(ref _buildFinishTime, value); + } + + public BuildResultState GetBuildState() + { + if (CurrentBuildState == BuildState.InProgress) + { + return BuildResultState.Unknown; + } + else if (CurrentBuildState == BuildState.Done) + { + //TODO Decied what happened + if (BuildAction == BuildActions.BuildActionRebuildAll) + return BuildResultState.RebuildCancelled; + if (BuildAction == BuildActions.BuildActionClean) + return BuildResultState.CleanCancelled; + if (BuildAction == BuildActions.BuildActionBuild) + return BuildResultState.BuildCancelled; + else + return BuildResultState.Unknown; + + if (BuildAction == BuildActions.BuildActionRebuildAll) + return BuildResultState.RebuildFailed; + if (BuildAction == BuildActions.BuildActionClean) + return BuildResultState.CleanFailed; + if (BuildAction == BuildActions.BuildActionBuild) + return BuildResultState.BuildFailed; + else + return BuildResultState.Unknown; + + if (BuildAction == BuildActions.BuildActionRebuildAll) + return BuildResultState.RebuildSucceeded; + if (BuildAction == BuildActions.BuildActionClean) + return BuildResultState.CleanSucceeded; + if (BuildAction == BuildActions.BuildActionBuild) + return BuildResultState.BuildSucceeded; + else + return BuildResultState.Unknown; + + if (BuildAction == BuildActions.BuildActionRebuildAll) + return BuildResultState.RebuildSucceededWithErrors; + if (BuildAction == BuildActions.BuildActionClean) + return BuildResultState.CleanSucceededWithErrors; + if (BuildAction == BuildActions.BuildActionBuild) + return BuildResultState.BuildSucceededWithErrors; + else + return BuildResultState.Unknown; + } + else + { + return BuildResultState.Unknown; + } + } + } +} diff --git a/src/BuildVision.UI/Models/BuildProgressSettings.cs b/src/BuildVision.UI/Models/BuildProgressSettings.cs deleted file mode 100644 index f0b5c17c..00000000 --- a/src/BuildVision.UI/Models/BuildProgressSettings.cs +++ /dev/null @@ -1,14 +0,0 @@ -using BuildVision.UI.Models; -using System.Runtime.Serialization; - -namespace BuildVision.UI.Settings.Models.BuildProgress -{ - public class BuildProgressSettings - { - public bool TaskBarProgressEnabled { get; set; } - - public ResetTaskBarItemInfoCondition ResetTaskBarProgressAfterBuildDone { get; set; } = ResetTaskBarItemInfoCondition.ByMouseClick; - - public int ResetTaskBarProgressDelay { get; set; } = 5000; - } -} \ No newline at end of file diff --git a/src/BuildVision.UI/Models/GridSettings.cs b/src/BuildVision.UI/Models/GridSettings.cs deleted file mode 100644 index 8ad52998..00000000 --- a/src/BuildVision.UI/Models/GridSettings.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using BuildVision.Common; -using BuildVision.UI.DataGrid; -using BuildVision.UI.Settings.Models.Columns; -using BuildVision.UI.Models; -using BuildVision.UI.Settings.Models.Sorting; - -namespace BuildVision.UI.Settings.Models -{ - public class GridSettings : SettingsBase - { - private GridColumnSettingsCollection _columns; - - private string _groupName; - - private string _groupHeaderFormat; - - private SortDescription _sort; - - private List<string> _collapsedGroups; - - private static string[] _groupHeaderFormatArgs; - - public GridColumnSettingsCollection Columns => _columns ?? (_columns = new GridColumnSettingsCollection()); - - public IEnumerable<GridColumnSettings> SortableColumnsUIList - { - get - { - yield return GridColumnSettings.Empty; - foreach (GridColumnSettings column in Columns.Where(x => ColumnsManager.ColumnIsSortable(x.PropertyNameId))) - yield return column; - } - } - - public IEnumerable<GridColumnSettings> GroupableColumnsUIList - { - get - { - yield return GridColumnSettings.Empty; - foreach (GridColumnSettings column in Columns.Where(ColumnsManager.ColumnIsGroupable)) - yield return column; - } - } - - public string GroupName - { - get => _groupName ?? (_groupName = string.Empty); - set => _groupName = value; - } - - /// <summary> - /// User-friendly header format for groups. - /// For example, "{title}: {value} - {count} items". - /// Available arguments see in <see cref="GroupHeaderFormatArgs"/>. - /// </summary> - public string GroupHeaderFormat - { - get => _groupHeaderFormat ?? (_groupHeaderFormat = "{title}: {value}"); - set => _groupHeaderFormat = value; - } - - public string GroupHeaderRawFormat => ConvertGroupHeaderToRawFormat(GroupHeaderFormat); - - public static string[] GroupHeaderFormatArgs => _groupHeaderFormatArgs ?? (_groupHeaderFormatArgs = new[] { "title", "value", "count" }); - - public bool ShowColumnsHeader { get; set; } = true; - - public SortDescription Sort - { - get => _sort ?? (_sort = new SortDescription(SortOrder.Ascending, "BuildOrder")); - set => _sort = value; - } - - public List<string> CollapsedGroups => _collapsedGroups ?? (_collapsedGroups = new List<string>()); - - /// <summary> - /// Converts user-friendly string format with <see cref="GroupHeaderFormatArgs"/> arguments - /// into system format string (with {0},{1},... arguments). - /// </summary> - private static string ConvertGroupHeaderToRawFormat(string userFriendlyFormatString) - { - if (string.IsNullOrEmpty(userFriendlyFormatString)) - return string.Empty; - - string rawFormat = userFriendlyFormatString; - for (int i = 0; i < GroupHeaderFormatArgs.Length; i++) - rawFormat = rawFormat.Replace("{" + GroupHeaderFormatArgs[i], "{" + i); - - return rawFormat; - } - } -} \ No newline at end of file diff --git a/src/BuildVision.UI/Models/SolutionItem.cs b/src/BuildVision.UI/Models/SolutionModel.cs similarity index 56% rename from src/BuildVision.UI/Models/SolutionItem.cs rename to src/BuildVision.UI/Models/SolutionModel.cs index b1d65eaa..a03e5203 100644 --- a/src/BuildVision.UI/Models/SolutionItem.cs +++ b/src/BuildVision.UI/Models/SolutionModel.cs @@ -1,12 +1,17 @@ using BuildVision.Common; -using System.Collections.Generic; -using System.Collections.ObjectModel; +using BuildVision.Contracts.Models; - -namespace BuildVision.UI.Models +namespace BuildVision.Core { - public class SolutionItem : BindableBase + public class SolutionModel : BindableBase, ISolutionModel { + private string _fileName; + public string FileName + { + get => _fileName; + set => SetProperty(ref _fileName, value); + } + private string _name; public string Name { @@ -27,15 +32,5 @@ public bool IsEmpty get => _isEmpty; set => SetProperty(ref _isEmpty, value); } - - public ObservableCollection<ProjectItem> Projects { get; } - - public List<ProjectItem> AllProjects { get; } - - public SolutionItem() - { - Projects = new ObservableRangeCollection<ProjectItem>(); - AllProjects = new List<ProjectItem>(); - } } -} \ No newline at end of file +} diff --git a/src/BuildVision.UI/Models/WindowSettings.cs b/src/BuildVision.UI/Models/WindowSettings.cs deleted file mode 100644 index d23a0da9..00000000 --- a/src/BuildVision.UI/Models/WindowSettings.cs +++ /dev/null @@ -1,22 +0,0 @@ -using BuildVision.Common; -using BuildVision.UI.Models; -using BuildVision.UI.Settings.Models.ToolWindow; - -namespace BuildVision.UI.Settings.Models -{ - public class WindowSettings : SettingsBase - { - public WindowStateAction WindowActionOnBuildBegin { get; set; } - - public WindowStateAction WindowActionOnBuildSuccess { get; set; } - - public WindowStateAction WindowActionOnBuildError { get; set; } - - public WindowSettings() - { - WindowActionOnBuildBegin = new WindowStateAction(WindowState.Show); - WindowActionOnBuildSuccess = new WindowStateAction(WindowState.Nothing); - WindowActionOnBuildError = new WindowStateAction(WindowState.Show); - } - } -} diff --git a/src/BuildVision.UI/Settings/Models/BaseGridColumnSettings.cs b/src/BuildVision.UI/Settings/Models/BaseGridColumnSettings.cs new file mode 100644 index 00000000..82127fc4 --- /dev/null +++ b/src/BuildVision.UI/Settings/Models/BaseGridColumnSettings.cs @@ -0,0 +1,31 @@ +using System; +using System.Runtime.Serialization; + +namespace BuildVision.Contracts +{ + public abstract class BaseGridColumnSettingsAttribute : Attribute + { + public string Header { get; set; } + + public bool Visible { get; set; } + + /// <remarks> + /// -1 for auto. + /// </remarks> + public int DisplayIndex { get; set; } + + /// <remarks> + /// double.NaN for auto. + /// </remarks> + public double Width { get; set; } + + public string ValueStringFormat { get; set; } + + protected BaseGridColumnSettingsAttribute() + { + Width = double.NaN; + DisplayIndex = -1; + Visible = true; + } + } +} diff --git a/src/BuildVision.UI/Models/BuildMessagesSettings.cs b/src/BuildVision.UI/Settings/Models/BuildMessagesSettings.cs similarity index 100% rename from src/BuildVision.UI/Models/BuildMessagesSettings.cs rename to src/BuildVision.UI/Settings/Models/BuildMessagesSettings.cs diff --git a/src/BuildVision.UI/Settings/Models/BuildProgressSettings.cs b/src/BuildVision.UI/Settings/Models/BuildProgressSettings.cs new file mode 100644 index 00000000..24032fd3 --- /dev/null +++ b/src/BuildVision.UI/Settings/Models/BuildProgressSettings.cs @@ -0,0 +1,14 @@ +using BuildVision.UI.Models; +using System.Runtime.Serialization; + +namespace BuildVision.UI.Settings.Models.BuildProgress +{ + public class BuildProgressSettings + { + public bool TaskBarProgressEnabled { get; set; } + + public ResetTaskBarItemInfoCondition ResetTaskBarProgressAfterBuildDone { get; set; } = ResetTaskBarItemInfoCondition.ByMouseClick; + + public int ResetTaskBarProgressDelay { get; set; } = 5000; + } +} diff --git a/src/BuildVision.UI/Models/ControlSettings.cs b/src/BuildVision.UI/Settings/Models/ControlSettings.cs similarity index 100% rename from src/BuildVision.UI/Models/ControlSettings.cs rename to src/BuildVision.UI/Settings/Models/ControlSettings.cs diff --git a/src/BuildVision.UI/Models/GeneralSettings.cs b/src/BuildVision.UI/Settings/Models/GeneralSettings.cs similarity index 99% rename from src/BuildVision.UI/Models/GeneralSettings.cs rename to src/BuildVision.UI/Settings/Models/GeneralSettings.cs index a038f01d..9e6e20f8 100644 --- a/src/BuildVision.UI/Models/GeneralSettings.cs +++ b/src/BuildVision.UI/Settings/Models/GeneralSettings.cs @@ -30,4 +30,4 @@ public GeneralSettings() ShowWarningSignForBuilds = true; } } -} \ No newline at end of file +} diff --git a/src/BuildVision.UI/Models/GridColumnSettings.cs b/src/BuildVision.UI/Settings/Models/GridColumnSettings.cs similarity index 83% rename from src/BuildVision.UI/Models/GridColumnSettings.cs rename to src/BuildVision.UI/Settings/Models/GridColumnSettings.cs index d6780355..7171ea9a 100644 --- a/src/BuildVision.UI/Models/GridColumnSettings.cs +++ b/src/BuildVision.UI/Settings/Models/GridColumnSettings.cs @@ -9,7 +9,7 @@ public class GridColumnSettings : BaseGridColumnSettingsAttribute PropertyNameId = string.Empty, Header = Resources.NoneMenuItem }; - + public string PropertyNameId { get; set; } private GridColumnSettings() @@ -17,11 +17,11 @@ private GridColumnSettings() } public GridColumnSettings( - string propertyNameId, - string header, - bool visible, - int displayIndex, - double width, + string propertyNameId, + string header, + bool visible, + int displayIndex, + double width, string valueStringFormat) { PropertyNameId = propertyNameId; @@ -32,4 +32,4 @@ public GridColumnSettings( ValueStringFormat = valueStringFormat; } } -} \ No newline at end of file +} diff --git a/src/BuildVision.UI/Settings/Models/GridSettings.cs b/src/BuildVision.UI/Settings/Models/GridSettings.cs new file mode 100644 index 00000000..c695fb06 --- /dev/null +++ b/src/BuildVision.UI/Settings/Models/GridSettings.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.Linq; +using BuildVision.Common; +using BuildVision.UI.DataGrid; +using BuildVision.UI.Settings.Models.Columns; +using BuildVision.UI.Models; +using BuildVision.UI.Settings.Models.Sorting; + +namespace BuildVision.UI.Settings.Models +{ + public class GridSettings : SettingsBase + { + private GridColumnSettingsCollection _columns; + + private string _groupName; + + private string _groupHeaderFormat; + + private SortDescription _sort; + + private List<string> _collapsedGroups; + + private static string[] _groupHeaderFormatArgs; + + public GridColumnSettingsCollection Columns => _columns ?? (_columns = new GridColumnSettingsCollection()); + + public IEnumerable<GridColumnSettings> SortableColumnsUIList + { + get + { + yield return GridColumnSettings.Empty; + foreach (GridColumnSettings column in Columns.Where(x => ColumnsManager.ColumnIsSortable(x.PropertyNameId))) + yield return column; + } + } + + public IEnumerable<GridColumnSettings> GroupableColumnsUIList + { + get + { + yield return GridColumnSettings.Empty; + foreach (GridColumnSettings column in Columns.Where(ColumnsManager.ColumnIsGroupable)) + yield return column; + } + } + + public string GroupName + { + get => _groupName ?? (_groupName = string.Empty); + set => _groupName = value; + } + + /// <summary> + /// User-friendly header format for groups. + /// For example, "{title}: {value} - {count} items". + /// Available arguments see in <see cref="GroupHeaderFormatArgs"/>. + /// </summary> + public string GroupHeaderFormat + { + get => _groupHeaderFormat ?? (_groupHeaderFormat = "{title}: {value}"); + set => _groupHeaderFormat = value; + } + + public string GroupHeaderRawFormat => ConvertGroupHeaderToRawFormat(GroupHeaderFormat); + + public static string[] GroupHeaderFormatArgs => _groupHeaderFormatArgs ?? (_groupHeaderFormatArgs = new[] { "title", "value", "count" }); + + public bool ShowColumnsHeader { get; set; } = true; + + public SortDescription Sort + { + get => _sort ?? (_sort = new SortDescription(SortOrder.Ascending, "BuildOrder")); + set => _sort = value; + } + + public List<string> CollapsedGroups => _collapsedGroups ?? (_collapsedGroups = new List<string>()); + + /// <summary> + /// Converts user-friendly string format with <see cref="GroupHeaderFormatArgs"/> arguments + /// into system format string (with {0},{1},... arguments). + /// </summary> + private static string ConvertGroupHeaderToRawFormat(string userFriendlyFormatString) + { + if (string.IsNullOrEmpty(userFriendlyFormatString)) + return string.Empty; + + string rawFormat = userFriendlyFormatString; + for (int i = 0; i < GroupHeaderFormatArgs.Length; i++) + rawFormat = rawFormat.Replace("{" + GroupHeaderFormatArgs[i], "{" + i); + + return rawFormat; + } + } +} diff --git a/src/BuildVision.UI/Models/ProjectItemSettings.cs b/src/BuildVision.UI/Settings/Models/ProjectItemSettings.cs similarity index 98% rename from src/BuildVision.UI/Models/ProjectItemSettings.cs rename to src/BuildVision.UI/Settings/Models/ProjectItemSettings.cs index 93108f5d..f1a451ed 100644 --- a/src/BuildVision.UI/Models/ProjectItemSettings.cs +++ b/src/BuildVision.UI/Settings/Models/ProjectItemSettings.cs @@ -3,7 +3,7 @@ namespace BuildVision.UI.Settings.Models { public class ProjectItemSettings : SettingsBase - { + { public BuildOutputFileTypes CopyBuildOutputFileTypesToClipboard { get; set; } public ProjectItemSettings() diff --git a/src/BuildVision.UI/Settings/Models/WindowSettings.cs b/src/BuildVision.UI/Settings/Models/WindowSettings.cs new file mode 100644 index 00000000..91acb467 --- /dev/null +++ b/src/BuildVision.UI/Settings/Models/WindowSettings.cs @@ -0,0 +1,22 @@ +using BuildVision.Common; +using BuildVision.UI.Models; +using BuildVision.UI.Settings.Models.ToolWindow; + +namespace BuildVision.UI.Settings.Models +{ + public class WindowSettings : SettingsBase + { + public WindowStateAction WindowActionOnBuildBegin { get; set; } + + public WindowStateAction WindowActionOnBuildSuccess { get; set; } + + public WindowStateAction WindowActionOnBuildError { get; set; } + + public WindowSettings() + { + WindowActionOnBuildBegin = new WindowStateAction(WindowState.Show); + WindowActionOnBuildSuccess = new WindowStateAction(WindowState.Nothing); + WindowActionOnBuildError = new WindowStateAction(WindowState.Show); + } + } +} diff --git a/src/BuildVision.UI/ViewModels/BuildVisionPaneViewModel.cs b/src/BuildVision.UI/ViewModels/BuildVisionPaneViewModel.cs index 4ea77a04..bcb15ce8 100644 --- a/src/BuildVision.UI/ViewModels/BuildVisionPaneViewModel.cs +++ b/src/BuildVision.UI/ViewModels/BuildVisionPaneViewModel.cs @@ -28,6 +28,8 @@ using BuildVision.Views.Settings; using BuildVision.Exports.Services; using BuildVision.Exports.ViewModels; +using BuildVision.Exports.Providers; +using BuildVision.Contracts.Models; namespace BuildVision.UI.ViewModels { @@ -46,6 +48,8 @@ public bool HideUpToDateTargets public ControlSettings ControlSettings { get; } + public IBuildInformationModel BuildInformationModel { get; set; } + public string GridGroupPropertyName { get { return ControlSettings.GridSettings.GroupName; } @@ -179,6 +183,7 @@ public DataGridHeadersVisibility GridHeadersVisibility private ProjectItem _selectedProjectItem; private readonly IBuildService _buildManager; + private readonly IBuildInformationProvider _buildInformationProvider; public ProjectItem SelectedProjectItem { @@ -187,9 +192,11 @@ public ProjectItem SelectedProjectItem } [ImportingConstructor] - public BuildVisionPaneViewModel(IBuildService buildManager, VisualStudioSolution solution, IPackageSettingsProvider settingsProvider) + public BuildVisionPaneViewModel(IBuildService buildManager, IBuildInformationProvider buildInformationProvider, IPackageSettingsProvider settingsProvider) { _buildManager = buildManager; + _buildInformationProvider = buildInformationProvider; + BuildInformationModel = _buildInformationProvider.GetBuildInformationModel(); ControlSettings = settingsProvider.Settings; BuildProgressViewModel = new BuildProgressViewModel(ControlSettings); } diff --git a/src/BuildVision.UI/ViewModels/SolutionModel.cs b/src/BuildVision.UI/ViewModels/SolutionModel.cs deleted file mode 100644 index ce8ae774..00000000 --- a/src/BuildVision.UI/ViewModels/SolutionModel.cs +++ /dev/null @@ -1,93 +0,0 @@ -using BuildVision.Common; - -namespace BuildVision.Core -{ - public class SolutionModel : BindableBase - { - public string State { get; set; } = "StandBy"; - - private int _errorCount = -1; - public int ErrorCount - { - get => _errorCount; - set => SetProperty(ref _errorCount, value); - } - - private int _warningsCount = -1; - public int WarningsCount - { - get => _warningsCount; - set => SetProperty(ref _warningsCount, value); - } - - private int _messagesCount = -1; - public int MessagesCount - { - get => _messagesCount; - set => SetProperty(ref _messagesCount, value); - } - - private int _succeededProjectsCount = -1; - public int SucceededProjectsCount - { - get => _warningsCount; - set => SetProperty(ref _succeededProjectsCount, value); - } - - private int _upToDateProjectsCount = -1; - public int UpToDateProjectsCount - { - get => _warningsCount; - set => SetProperty(ref _upToDateProjectsCount, value); - } - - private int _failedProjectsCount = -1; - public int FailedProjectsCount - { - get => _warningsCount; - set => SetProperty(ref _failedProjectsCount, value); - } - - private int _warnedProjectsCount = -1; - public int WarnedProjectsCount - { - get => _warningsCount; - set => SetProperty(ref _warnedProjectsCount, value); - } - - private string _stateMessage = ""; - public string StateMessage - { - get => _stateMessage; - set => SetProperty(ref _stateMessage, value); - } - - private string _fileName; - public string FileName - { - get => _fileName; - set => SetProperty(ref _fileName, value); - } - - private string _name; - public string Name - { - get => _name; - set => SetProperty(ref _name, value); - } - - private string _fullName; - public string FullName - { - get => _fullName; - set => SetProperty(ref _fullName, value); - } - - private bool _isEmpty = true; - public bool IsEmpty - { - get => _isEmpty; - set => SetProperty(ref _isEmpty, value); - } - } -} diff --git a/src/BuildVision.UI/ViewModels/VisualStudioSolution.cs b/src/BuildVision.UI/ViewModels/VisualStudioSolution.cs deleted file mode 100644 index bab610c8..00000000 --- a/src/BuildVision.UI/ViewModels/VisualStudioSolution.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using BuildVision.Common; -using BuildVision.Contracts; -using BuildVision.UI.Contracts; -using BuildVision.UI.Models; - -namespace BuildVision.Core -{ - - public class VisualStudioSolution : BindableBase - { - public BuildState CurrentBuildState { get; set; } - public BuildResultState ResultState => GetBuildState(); - public BuildActions BuildAction { get; set; } - public BuildScopes BuildScope { get; set; } - public DateTime? BuildStartTime { get; set; } - public DateTime? BuildFinishTime { get; set; } - - public ObservableCollection<ProjectItem> Projects { get; } - - public VisualStudioSolution() - { - Projects = new ObservableCollection<ProjectItem>(); - } - - public BuildResultState GetBuildState() - { - if (CurrentBuildState == BuildState.InProgress) - { - return BuildResultState.Unknown; - } - else if (CurrentBuildState == BuildState.Done) - { - //TODO Decied what happened - if (BuildAction == BuildActions.BuildActionRebuildAll) - return BuildResultState.RebuildCancelled; - if (BuildAction == BuildActions.BuildActionClean) - return BuildResultState.CleanCancelled; - if (BuildAction == BuildActions.BuildActionBuild) - return BuildResultState.BuildCancelled; - else - return BuildResultState.Unknown; - - if (BuildAction == BuildActions.BuildActionRebuildAll) - return BuildResultState.RebuildFailed; - if (BuildAction == BuildActions.BuildActionClean) - return BuildResultState.CleanFailed; - if (BuildAction == BuildActions.BuildActionBuild) - return BuildResultState.BuildFailed; - else - return BuildResultState.Unknown; - - if (BuildAction == BuildActions.BuildActionRebuildAll) - return BuildResultState.RebuildSucceeded; - if (BuildAction == BuildActions.BuildActionClean) - return BuildResultState.CleanSucceeded; - if (BuildAction == BuildActions.BuildActionBuild) - return BuildResultState.BuildSucceeded; - else - return BuildResultState.Unknown; - - if (BuildAction == BuildActions.BuildActionRebuildAll) - return BuildResultState.RebuildSucceededWithErrors; - if (BuildAction == BuildActions.BuildActionClean) - return BuildResultState.CleanSucceededWithErrors; - if (BuildAction == BuildActions.BuildActionBuild) - return BuildResultState.BuildSucceededWithErrors; - else - return BuildResultState.Unknown; - } - else - { - return BuildResultState.Unknown; - } - } - } - - - /* - * General - * - BuildState / ResultState - * - StateMessage - * - ErrorsCount - * - WarningsCount - * - InformationCount - * - SucceededProjects - * - UpToDateProjects - * - WarningProjects - * - FailedProjects - * - * Projects - * - * Actions - * - Build Solution - * - Rebuild Solution - * - Clean Solution - * - Cancel - * * - * */ -} diff --git a/src/BuildVision/BuildVision.csproj b/src/BuildVision/BuildVision.csproj index bc863a08..05676a66 100644 --- a/src/BuildVision/BuildVision.csproj +++ b/src/BuildVision/BuildVision.csproj @@ -91,13 +91,18 @@ <Reference Include="System.Xaml" /> </ItemGroup> <ItemGroup> + <Compile Include="Services\BuildInformationProvider.cs" /> + <Compile Include="Services\BuildingProjectsProvider.cs" /> + <Compile Include="Services\IBuildingProjectsProvider.cs" /> + <Compile Include="Services\ISolutionProvider.cs" /> + <Compile Include="Services\SolutionProvider.cs" /> <Compile Include="Helpers\ProjectIdentifierGenerator.cs" /> <Compile Include="Core\BuildVisionPackage.cs" /> <Compile Include="Core\ServiceProviderExports.cs" /> <Compile Include="Core\ServiceProviderPackage.cs" /> <Compile Include="Core\Services.cs" /> <Compile Include="Core\SolutionBuildEvents.cs" /> - <Compile Include="Core\StatusBarNotificationService.cs" /> + <Compile Include="Services\StatusBarNotificationService.cs" /> <Compile Include="Helpers\BuildEventContextExtensions.cs" /> <Compile Include="Helpers\BuildMessageEventArgsExtensions.cs" /> <Compile Include="Helpers\EnvDTEProjectKinds.cs" /> diff --git a/src/BuildVision/Core/BuildVisionPackage.cs b/src/BuildVision/Core/BuildVisionPackage.cs index 5882d334..927267ba 100644 --- a/src/BuildVision/Core/BuildVisionPackage.cs +++ b/src/BuildVision/Core/BuildVisionPackage.cs @@ -6,6 +6,7 @@ using System.Windows; using BuildVision.Common; using BuildVision.Contracts; +using BuildVision.Exports.Providers; using BuildVision.Helpers; using BuildVision.Tool; using BuildVision.Tool.Building; @@ -41,12 +42,9 @@ namespace BuildVision.Core // This attribute registers a tool window exposed by this package. [ProvideToolWindow(typeof(BuildVisionPane))] [Guid(PackageGuids.GuidBuildVisionPackageString)] - //[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionOpening_string, PackageAutoLoadFlags.BackgroundLoad)] [ProvideBindingPath] [ProvideBindingPath(SubPath = "Lib")] - // TODO: Add ProvideProfileAttribute for each DialogPage and implement IVsUserSettings, IVsUserSettingsQuery. [ProvideProfile(typeof(GeneralSettingsDialogPage), PackageSettingsProvider.settingsCategoryName, "General Options", 0, 0, true)] - // TODO: ProvideOptionPage keywords. [ProvideOptionPage(typeof(GeneralSettingsDialogPage), "BuildVision", "General", 0, 0, true)] [ProvideOptionPage(typeof(WindowSettingsDialogPage), "BuildVision", "Tool Window", 0, 0, true)] [ProvideOptionPage(typeof(GridSettingsDialogPage), "BuildVision", "Projects Grid", 0, 0, true)] @@ -59,13 +57,14 @@ public sealed partial class BuildVisionPackage : AsyncPackage, IPackageContext private SolutionEvents _solutionEvents; private BuildVisionPaneViewModel _viewModel; private IVsSolutionBuildManager2 _solutionBuildManager; + private IVsSolutionBuildManager5 _solutionBuildManager4; + private IBuildInformationProvider _buildInformationProvider; private uint _updateSolutionEvents4Cookie; private readonly Guid _parsingErrorsLoggerId = new Guid("{64822131-DC4D-4087-B292-61F7E06A7B39}"); private BuildOutputLogger _buildLogger; - private Solution _vsSolution; - private IVsSolutionBuildManager5 _solutionBuildManager4; - private SolutionModel _solutionState; private SolutionBuildEvents _solutionBuildEvents; + private ISolutionProvider _solutionProvider; + private IBuildingProjectsProvider _buildingProjectsProvider; public ControlSettings ControlSettings { get; set; } @@ -88,11 +87,13 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke var menuToolWin = new OleMenuCommand(ShowToolWindowAsync, toolwndCommandId); mcs.AddCommand(menuToolWin); } - _solutionBuildManager = ServiceProvider.GlobalProvider.GetService(typeof(SVsSolutionBuildManager)) as IVsSolutionBuildManager2; - _solutionBuildManager4 = ServiceProvider.GlobalProvider.GetService(typeof(SVsSolutionBuildManager)) as IVsSolutionBuildManager5; + _solutionBuildManager = await GetServiceAsync(typeof(SVsSolutionBuildManager)) as IVsSolutionBuildManager2; + _solutionBuildManager4 = await GetServiceAsync(typeof(SVsSolutionBuildManager)) as IVsSolutionBuildManager5; + _buildInformationProvider = await GetServiceAsync(typeof(IBuildInformationProvider)) as IBuildInformationProvider; + _solutionProvider = await GetServiceAsync(typeof(ISolutionProvider)) as ISolutionProvider; + _buildingProjectsProvider = await GetServiceAsync(typeof(IBuildingProjectsProvider)) as IBuildingProjectsProvider; IPackageContext packageContext = this; - _solutionEvents = _dte.Events.SolutionEvents; _solutionEvents.BeforeClosing += SolutionEvents_BeforeClosing; _solutionEvents.AfterClosing += SolutionEvents_AfterClosing; @@ -103,8 +104,8 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke SolutionEvents_Opened(); } - var toolWindow = GetWindowPane(typeof(BuildVisionPane)); - _viewModel = BuildVisionPane.GetViewModel(toolWindow); + //var toolWindow = GetWindowPane(typeof(BuildVisionPane)); + //_viewModel = BuildVisionPane.GetViewModel(toolWindow); } private void SolutionEvents_BeforeClosing() @@ -117,22 +118,15 @@ private void SolutionEvents_BeforeClosing() private void SolutionEvents_Opened() { ThreadHelper.ThrowIfNotOnUIThread(); - _vsSolution = Services.Dte2.Solution; - _solutionState = _vsSolution.ToSolutionBuildState(); - //_solutionBuildEvents = new SolutionBuildEvents(_solutionState); + _solutionBuildEvents = new SolutionBuildEvents(_solutionProvider, _buildInformationProvider, _buildingProjectsProvider); _solutionBuildManager.AdviseUpdateSolutionEvents(_solutionBuildEvents, out _updateSolutionEvents4Cookie); _solutionBuildManager4.AdviseUpdateSolutionEvents4(_solutionBuildEvents, out _updateSolutionEvents4Cookie); - //_viewModel.ResetIndicators(ResetIndicatorMode.ResetValue); } private void SolutionEvents_AfterClosing() { ThreadHelper.ThrowIfNotOnUIThread(); - //_viewModel.TextCurrentState = Resources.BuildDoneText_BuildNotStarted; - ////_viewModel.ImageCurrentState = "TODO SET IMAGE"//VectorResources.TryGet(BuildImages.BuildActionResourcesUri, "StandBy"); - //_viewModel.ProjectsList.Clear(); - //_viewModel.ResetIndicators(ResetIndicatorMode.Disable); - _viewModel.BuildProgressViewModel.ResetTaskBarInfo(); + //_viewModel.BuildProgressViewModel.ResetTaskBarInfo(); } private async void ShowToolWindowAsync(object sender, EventArgs e) diff --git a/src/BuildVision/Core/ServiceProviderPackage.cs b/src/BuildVision/Core/ServiceProviderPackage.cs index 85c48306..5c240024 100644 --- a/src/BuildVision/Core/ServiceProviderPackage.cs +++ b/src/BuildVision/Core/ServiceProviderPackage.cs @@ -2,7 +2,9 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using BuildVision.Exports.Providers; using BuildVision.Views.Settings; +using Microsoft; using Microsoft.VisualStudio.Shell; using Task = System.Threading.Tasks.Task; @@ -11,12 +13,18 @@ namespace BuildVision.Core [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] [Guid(PackageGuids.GuidBuildVisionServiceProvider)] [ProvideService(typeof(IPackageSettingsProvider), IsAsyncQueryable = true)] + [ProvideService(typeof(IBuildInformationProvider), IsAsyncQueryable = true)] + [ProvideService(typeof(ISolutionProvider), IsAsyncQueryable = true)] + [ProvideService(typeof(IBuildingProjectsProvider), IsAsyncQueryable = true)] public sealed class ServiceProviderPackage : AsyncPackage { protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress<ServiceProgressData> progress) { await Task.CompletedTask; AddService(typeof(IPackageSettingsProvider), CreateServiceAsync, true); + AddService(typeof(IBuildInformationProvider), CreateServiceAsync, true); + AddService(typeof(ISolutionProvider), CreateServiceAsync, true); + AddService(typeof(IBuildingProjectsProvider), CreateServiceAsync, true); } async Task<object> CreateServiceAsync(IAsyncServiceContainer container, CancellationToken cancellation, Type serviceType) @@ -25,8 +33,34 @@ async Task<object> CreateServiceAsync(IAsyncServiceContainer container, Cancella { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellation); var sp = new ServiceProvider(Services.Dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider); + Assumes.Present(sp); return new PackageSettingsProvider(sp); } + else if (serviceType == typeof(IBuildInformationProvider)) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellation); + var sp = new ServiceProvider(Services.Dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider); + Assumes.Present(sp); + return new BuildInformationProvider(sp); + } + else if (serviceType == typeof(ISolutionProvider)) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellation); + var sp = new ServiceProvider(Services.Dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider); + Assumes.Present(sp); + return new SolutionProvider(sp); + } + else if (serviceType == typeof(IBuildingProjectsProvider)) + { + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(cancellation); + var sp = new ServiceProvider(Services.Dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider); + Assumes.Present(sp); + var solutionProvider = sp.GetService(typeof(ISolutionProvider)) as ISolutionProvider; + Assumes.Present(solutionProvider); + var buildInformationProvider = sp.GetService(typeof(IBuildInformationProvider)) as IBuildInformationProvider; + Assumes.Present(buildInformationProvider); + return new BuildingProjectsProvider(solutionProvider, buildInformationProvider); + } else { throw new Exception("Not found"); diff --git a/src/BuildVision/Core/SolutionBuildEvents.cs b/src/BuildVision/Core/SolutionBuildEvents.cs index 07fc7d4b..5aef26d7 100644 --- a/src/BuildVision/Core/SolutionBuildEvents.cs +++ b/src/BuildVision/Core/SolutionBuildEvents.cs @@ -4,6 +4,7 @@ using System.Threading; using BuildVision.Common; using BuildVision.Contracts; +using BuildVision.Exports.Providers; using BuildVision.Helpers; using BuildVision.Tool.Building; using BuildVision.Tool.Models; @@ -20,309 +21,56 @@ namespace BuildVision.Core public class SolutionBuildEvents : IVsUpdateSolutionEvents2, IVsUpdateSolutionEvents4 { - private readonly Guid _parsingErrorsLoggerId = new Guid("{64822131-DC4D-4087-B292-61F7E06A7B39}"); - public BuildOutputLogger _buildLogger; // This needs to be static because it is shared accross multiple instances + private readonly ISolutionProvider _solutionProvider; + private readonly IBuildInformationProvider _buildInformationProvider; + private readonly IBuildingProjectsProvider _buildingProjectsProvider; - public VisualStudioSolution VisualStudioSolution { get; } - - private BuildEvents _buildEvents; - private bool _buildCancelled; - private bool _buildCancelledInternally; - private bool _buildErrorIsNavigated; - private string _origTextCurrentState; - - public SolutionBuildEvents(VisualStudioSolution solutionBuildState) + public SolutionBuildEvents( + ISolutionProvider solutionProvider, + IBuildInformationProvider buildInformationProvider, + IBuildingProjectsProvider buildingProjectsProvider) { - VisualStudioSolution = solutionBuildState; + _solutionProvider = solutionProvider; + _buildInformationProvider = buildInformationProvider; + _buildingProjectsProvider = buildingProjectsProvider; } public void UpdateSolution_BeginUpdateAction(uint dwAction) { - _buildCancelled = false; - _buildCancelledInternally = false; - _buildErrorIsNavigated = false; - - RegisterLogger(); - - VisualStudioSolution.Projects.Clear(); - VisualStudioSolution.Projects.AddRange(Services.Dte2.Solution.GetProjectItems()); - VisualStudioSolution.BuildStartTime = DateTime.Now; - VisualStudioSolution.BuildFinishTime = null; - VisualStudioSolution.CurrentBuildState = BuildState.InProgress; - VisualStudioSolution.BuildAction = StateConverterHelper.ConvertSolutionBuildFlagsToBuildAction(dwAction, (VSSOLNBUILDUPDATEFLAGS) dwAction); - - //TODO use settings - string message = new BuildMessagesFactory(new UI.Settings.Models.BuildMessagesSettings()).GetBuildBeginMajorMessage(VisualStudioSolution); - //_statusBarNotificationService.ShowTextWithFreeze(message); - _origTextCurrentState = message; - //VisualStudioSolution.StateMessage = _origTextCurrentState; // Set message - try - { - //ApplyToolWindowStateAction(_viewModel.ControlSettings.WindowSettings.WindowActionOnBuildBegin); - //if (_viewModel.ControlSettings.GeneralSettings.FillProjectListOnBuildBegin) - // _viewModel.ProjectsList.AddRange(_viewModel.SolutionItem.AllProjects); - - // Reset HeaderViewModel - //_viewModel.ResetIndicators(ResetIndicatorMode.ResetValue); - //int projectsCount = -1; - //projectsCount = GetProjectsCount(projectsCount); - //_viewModel.OnBuildBegin(projectsCount, this); - } - catch (Exception ex) - { - ex.TraceUnknownException(); - } + _buildInformationProvider.BuildStarted(dwAction); + _buildingProjectsProvider.ReloadCurrentProjects(); + //ApplyToolWindowStateAction(_viewModel.ControlSettings.WindowSettings.WindowActionOnBuildBegin); + //int projectsCount = -1; + //projectsCount = GetProjectsCount(projectsCount); + //_viewModel.OnBuildBegin(projectsCount, this); //_buildProcessCancellationToken = new CancellationTokenSource(); - //// Startbackground process - ////Task.Factory.StartNew(BuildEvents_BuildInProcess, _buildProcessCancellationToken.Token, _buildProcessCancellationToken.Token); + // Startbackground process + //Task.Factory.StartNew(BuildEvents_BuildInProcess, _buildProcessCancellationToken.Token, _buildProcessCancellationToken.Token); } public int UpdateProjectCfg_Begin(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, uint dwAction, ref int pfCancel) { - try - { - var projectItem = VisualStudioSolution.Projects.FirstOrDefault(item => ProjectIdentifierGenerator.GetIdentifierForProjectItem(item) == ProjectIdentifierGenerator.GetIdentifierForInteropTypes(pHierProj, pCfgProj)); - if (projectItem == null) - { - // In this case we are executing a batch build so we need to add the projectitem manually - projectItem = new UI.Models.ProjectItem(); - var configPair = pCfgProj.ToConfigurationTuple(); - SolutionProjectsExtensions.UpdateProperties(pHierProj.ToProject(), projectItem, configPair.Item1, configPair.Item2); - VisualStudioSolution.Projects.Add(projectItem); - } - - projectItem.State = GetProjectState(VisualStudioSolution.BuildAction); - projectItem.BuildFinishTime = null; - projectItem.BuildStartTime = DateTime.Now; - - // _viewModel.OnBuildProjectBegin(); - //if (BuildScope == BuildScopes.BuildScopeSolution && - // (BuildAction == BuildActions.BuildActionBuild || - // BuildAction == BuildActions.BuildActionRebuildAll)) - //{ - // currentProject.BuildOrder = _viewModel.BuildProgressViewModel.CurrentQueuePosOfBuildingProject; - //} - //if (!_viewModel.ProjectsList.Contains(currentProject)) - // _viewModel.ProjectsList.Add(currentProject); - //else if (_viewModel.ControlSettings.GeneralSettings.FillProjectListOnBuildBegin) - // _viewModel.OnPropertyChanged(nameof(BuildVisionPaneViewModel.GroupedProjectsList)); - //_viewModel.CurrentProject = currentProject; - } - catch (Exception ex) - { - ex.TraceUnknownException(); - } + _buildingProjectsProvider.ProjectBuildStarted(pHierProj, pCfgProj, pCfgSln, dwAction); return VSConstants.S_OK; } public int UpdateProjectCfg_Done(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, uint dwAction, int fSuccess, int fCancel) { - var currentProject = VisualStudioSolution.Projects.First(item => ProjectIdentifierGenerator.GetIdentifierForProjectItem(item) == ProjectIdentifierGenerator.GetIdentifierForInteropTypes(pHierProj, pCfgProj)); - Debug.WriteLine($"UpdateProjectCfg_Done {currentProject.UniqueName} ({currentProject.Configuration}|{currentProject.Platform})"); - //currentProject.Success = fSuccess == 1; - //ProjectState projectState; - //switch (SolutionBuildState.BuildAction) - //{ - // case BuildActions.BuildActionBuild: - // case BuildActions.BuildActionRebuildAll: - // if (currentProject.Success) - // { - // if (_viewModel.ControlSettings.GeneralSettings.ShowWarningSignForBuilds && buildedProject.ErrorsBox.WarningsCount > 0) - // projectState = ProjectState.BuildWarning; - // else - // { - // bool upToDate = (_buildLogger != null && _buildLogger.Projects != null - // && !_buildLogger.Projects.Exists(t => t.FileName == buildedProject.FileName)); - // if (upToDate) - // { - // // Because ErrorBox will be empty if project is UpToDate. - // buildedProject.ErrorsBox = currentProject.ErrorsBox; - // } - // projectState = upToDate ? ProjectState.UpToDate : ProjectState.BuildDone; - // } - // } - // else - // { - // bool canceled = (_buildCancelled && buildedProject.ErrorsBox.ErrorsCount == 0); - // projectState = canceled ? ProjectState.BuildCancelled : ProjectState.BuildError; - // } - // break; - - // case BuildActions.BuildActionClean: - // projectState = fSuccess == 1 ? ProjectState.CleanDone : ProjectState.CleanError; - // break; - - // case BuildActions.BuildActionDeploy: - // throw new InvalidOperationException("vsBuildActionDeploy not supported"); - - // default: - // throw new ArgumentOutOfRangeException(nameof(SolutionBuildState.BuildAction)); - //} - - //buildedProject.ProjectState = projectState; - //OnBuildProjectDone(new BuildProjectEventArgs(currentProject, projectState, eventTime, buildedProject)); - - //Debug.WriteLine($"UpdateProjectCfg_Done {proj.UniqueName} ({projConfiguration}) ({slnConfiguration}"); - - //if (e.ProjectState == ProjectState.BuildError && _viewModel.ControlSettings.GeneralSettings.StopBuildAfterFirstError) - // CancelBuildAsync(); - - //try - //{ - // ProjectItem currentProject = e.ProjectItem; - // currentProject.State = e.ProjectState; - // currentProject.BuildFinishTime = DateTime.Now; - // currentProject.UpdatePostBuildProperties(e.BuildedProjectInfo); - - // if (!_viewModel.ProjectsList.Contains(currentProject)) - // _viewModel.ProjectsList.Add(currentProject); - - // if (ReferenceEquals(_viewModel.CurrentProject, e.ProjectItem) && BuildingProjects.Any()) - // _viewModel.CurrentProject = BuildingProjects.Last(); - //} - //catch (Exception ex) - //{ - // ex.TraceUnknownException(); - //} - - //_viewModel.UpdateIndicators(this); - - //try - //{ - // _viewModel.OnBuildProjectDone(e.BuildedProjectInfo); - //} - //catch (Exception ex) - //{ - // ex.TraceUnknownException(); - //} + _buildingProjectsProvider.ProjectBuildFinished(pHierProj, pCfgProj, pCfgSln, fSuccess == 1, fCancel == 1); return VSConstants.S_OK; } public int UpdateSolution_Done(int fSucceeded, int fModified, int fCancelCommand) { - if (VisualStudioSolution.CurrentBuildState == BuildState.InProgress) - { - // Start command (F5), when Build is not required. - return VSConstants.S_OK; - } - - //try - //{ - // var settings = _viewModel.ControlSettings; - - // SetFinalStateForUnfinishedProjects(); - - // // Update header? This might be happening impliclty when updating solution - // //_viewModel.UpdateIndicators(this); + _buildInformationProvider.BuildFinished(fSucceeded == 1, fModified == 1, fCancelCommand == 1); - // var message = BuildMessages.GetBuildDoneMessage(_viewModel.SolutionItem, this, settings.BuildMessagesSettings); - // var buildDoneImage = BuildImages.GetBuildDoneImage(this, _viewModel.ProjectsList, out ControlTemplate stateImage); + var result = _buildInformationProvider.GetBuildInformationModel(); + var finishedProjects = _buildingProjectsProvider.GetBuildingProjects(); - // _statusBarNotificationService.ShowText(message); - // _viewModel.TextCurrentState = message; - // _viewModel.ImageCurrentState = buildDoneImage; - // _viewModel.ImageCurrentStateResult = stateImage; - // _viewModel.CurrentProject = null; - // _viewModel.OnBuildDone(this); - - // ApplyWindowState(settings); - // NavigateToBuildErrorIfNeeded(settings); - //} - //catch (Exception ex) - //{ - // ex.TraceUnknownException(); - //} - - VisualStudioSolution.BuildFinishTime = DateTime.Now; - VisualStudioSolution.CurrentBuildState = BuildState.Done; return VSConstants.S_OK; } - private ProjectState GetProjectState(BuildActions buildAction) - { - switch (buildAction) - { - case BuildActions.BuildActionBuild: - case BuildActions.BuildActionRebuildAll: - return ProjectState.Building; - - case BuildActions.BuildActionClean: - return ProjectState.Cleaning; - - case BuildActions.BuildActionDeploy: - throw new InvalidOperationException("vsBuildActionDeploy not supported"); - - default: - throw new ArgumentOutOfRangeException(nameof(buildAction)); - } - } - - private bool PlatformsIsEquals(string platformName1, string platformName2) - { - if (string.Compare(platformName1, platformName2, StringComparison.InvariantCultureIgnoreCase) == 0) - return true; - - // The ambiguity between Project.ActiveConfiguration.PlatformName and - // ProjectStartedEventArgs.ProjectPlatform in Microsoft.Build.Utilities.Logger - // (see BuildOutputLogger). - bool isAnyCpu1 = (platformName1 == "Any CPU" || platformName1 == "AnyCPU"); - bool isAnyCpu2 = (platformName2 == "Any CPU" || platformName2 == "AnyCPU"); - if (isAnyCpu1 && isAnyCpu2) - return true; - - return false; - } - - private void RegisterLogger() - { - _buildLogger = null; - RegisterLoggerResult result = BuildOutputLogger.Register(_parsingErrorsLoggerId, Microsoft.Build.Framework.LoggerVerbosity.Quiet, out _buildLogger); - if (result == RegisterLoggerResult.AlreadyExists) - { - _buildLogger.Projects?.Clear(); - } - } - - //public bool GetProjectItem(IBuildVisionPaneViewModel viewModel, BuildProjectContextEntry projectEntry, out ProjectItem projectItem) - //{ - // projectItem = projectEntry.ProjectItem; - // if (projectItem != null) - // return true; - - // string projectFile = projectEntry.FileName; - // if (ProjectExtensions.IsProjectHidden(projectFile)) - // return false; - - // var projectProperties = projectEntry.Properties; - // var project = viewModel.ProjectsList.FirstOrDefault(x => x.FullName == projectFile); - - - // if (projectProperties.ContainsKey("Configuration") && projectProperties.ContainsKey("Platform")) - // { - // string projectConfiguration = projectProperties["Configuration"]; - // string projectPlatform = projectProperties["Platform"]; - // projectItem = FindProjectItemInProjectsByUniqueName(viewModel, project.UniqueName, projectConfiguration, projectPlatform); - // if (projectItem == null) - // { - // TraceManager.Trace( - // string.Format("Project Item not found by: UniqueName='{0}', Configuration='{1}, Platform='{2}'.", - // project.UniqueName, - // projectConfiguration, - // projectPlatform), - // EventLogEntryType.Warning); - // return false; - // } - // } - // else - // { - // return false; - // } - - // projectEntry.ProjectItem = projectItem; - // return true; - //} - #region Interface Implementation public int UpdateSolution_Begin(ref int pfCancelUpdate) diff --git a/src/BuildVision/Services/BuildInformationProvider.cs b/src/BuildVision/Services/BuildInformationProvider.cs new file mode 100644 index 00000000..9fd80dfd --- /dev/null +++ b/src/BuildVision/Services/BuildInformationProvider.cs @@ -0,0 +1,127 @@ +using System; +using System.ComponentModel.Composition; +using System.IO; +using BuildVision.Contracts; +using BuildVision.Contracts.Models; +using BuildVision.Exports.Providers; +using BuildVision.Exports.Services; +using BuildVision.Tool.Building; +using BuildVision.Tool.Models; +using BuildVision.UI; +using BuildVision.UI.Common.Logging; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace BuildVision.Core +{ + [Export(typeof(IBuildInformationProvider))] + [PartCreationPolicy(CreationPolicy.Shared)] + public class BuildInformationProvider : IBuildInformationProvider + { + public BuildOutputLogger _buildLogger; + + private readonly Guid _parsingErrorsLoggerId = new Guid("{64822131-DC4D-4087-B292-61F7E06A7B39}"); + private readonly IServiceProvider _serviceProvider; + private Solution _solution; + private BuildInformationModel _buildInformationModel; + private BuildEvents _buildEvents; + private DTE2 _dte; + + [ImportingConstructor] + public BuildInformationProvider([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + _buildInformationModel = new BuildInformationModel(); + _buildEvents = (serviceProvider.GetService(typeof(DTE)) as DTE).Events.BuildEvents; + _buildEvents.OnBuildBegin += _buildEvents_OnBuildBegin; + } + + private void _buildEvents_OnBuildBegin(vsBuildScope scope, vsBuildAction action) + { + _buildInformationModel.BuildScope = (BuildScopes) scope; // we need to set buildscope explictly because it is not possible to get this via the other api + } + + public IBuildInformationModel GetBuildInformationModel() + { + return _buildInformationModel; + } + + public void BuildStarted(uint dwAction) + { + RegisterLogger(); + + _buildInformationModel.SucceededProjectsCount = 0; + _buildInformationModel.FailedProjectsCount = 0; + _buildInformationModel.WarnedProjectsCount = 0; + _buildInformationModel.UpToDateProjectsCount = 0; + _buildInformationModel.MessagesCount = 0; + _buildInformationModel.WarnedProjectsCount = 0; + _buildInformationModel.ErrorCount = 0; + _buildInformationModel.StateMessage = ""; + _buildInformationModel.BuildStartTime = DateTime.Now; + _buildInformationModel.BuildFinishTime = null; + _buildInformationModel.CurrentBuildState = BuildState.InProgress; + _buildInformationModel.BuildAction = StateConverterHelper.ConvertSolutionBuildFlagsToBuildAction(dwAction, (VSSOLNBUILDUPDATEFLAGS) dwAction); + //TODO use settings + //string message = new BuildMessagesFactory(new UI.Settings.Models.BuildMessagesSettings()).GetBuildBeginMajorMessage(VisualStudioSolution); + //_statusBarNotificationService.ShowTextWithFreeze(message); + //_origTextCurrentState = message; + //VisualStudioSolution.StateMessage = _origTextCurrentState; // Set message + } + + public void BuildUpdate() + { + //_buildInformationModel.StateMessage = _origTextCurrentState + BuildMessages.GetBuildBeginExtraMessage(this, labelsSettings); + } + + public void BuildFinished(bool success, bool modified, bool canceled) + { + //try + //{ + // var settings = _viewModel.ControlSettings; + + // SetFinalStateForUnfinishedProjects(); + + // // Update header? This might be happening impliclty when updating solution + // //_viewModel.UpdateIndicators(this); + + // var message = BuildMessages.GetBuildDoneMessage(_viewModel.SolutionItem, this, settings.BuildMessagesSettings); + // var buildDoneImage = BuildImages.GetBuildDoneImage(this, _viewModel.ProjectsList, out ControlTemplate stateImage); + + // _statusBarNotificationService.ShowText(message); + // _viewModel.TextCurrentState = message; + // _viewModel.ImageCurrentState = buildDoneImage; + // _viewModel.ImageCurrentStateResult = stateImage; + // _viewModel.CurrentProject = null; + // _viewModel.OnBuildDone(this); + + // ApplyWindowState(settings); + // NavigateToBuildErrorIfNeeded(settings); + //} + //catch (Exception ex) + //{ + // ex.TraceUnknownException(); + //} + + _buildInformationModel.BuildFinishTime = DateTime.Now; + if(success) + _buildInformationModel.CurrentBuildState = BuildState.Done; + else if(canceled) + _buildInformationModel.CurrentBuildState = BuildState.Cancelled; + else + _buildInformationModel.CurrentBuildState = BuildState.Failed; + } + + private void RegisterLogger() + { + _buildLogger = null; + RegisterLoggerResult result = BuildOutputLogger.Register(_parsingErrorsLoggerId, Microsoft.Build.Framework.LoggerVerbosity.Quiet, out _buildLogger); + if (result == RegisterLoggerResult.AlreadyExists) + { + _buildLogger.Projects?.Clear(); + } + } + } +} diff --git a/src/BuildVision/Services/BuildingProjectsProvider.cs b/src/BuildVision/Services/BuildingProjectsProvider.cs new file mode 100644 index 00000000..57a18a26 --- /dev/null +++ b/src/BuildVision/Services/BuildingProjectsProvider.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections.ObjectModel; +using System.ComponentModel.Composition; +using System.Linq; +using BuildVision.Common; +using BuildVision.Contracts; +using BuildVision.Contracts.Models; +using BuildVision.Exports.Providers; +using BuildVision.Helpers; +using BuildVision.Tool.Building; +using BuildVision.Tool.Models; +using BuildVision.UI.Common.Logging; +using BuildVision.UI.Models; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace BuildVision.Core +{ + [Export(typeof(IBuildInformationProvider))] + [PartCreationPolicy(CreationPolicy.Shared)] + public class BuildingProjectsProvider : IBuildingProjectsProvider + { + public BuildOutputLogger _buildLogger; + + private readonly Guid _parsingErrorsLoggerId = new Guid("{64822131-DC4D-4087-B292-61F7E06A7B39}"); + private readonly IServiceProvider _serviceProvider; + private readonly ISolutionProvider _solutionProvider; + private readonly IBuildInformationProvider _buildInformationProvider; + private ObservableCollection<ProjectItem> _projects; + + + [ImportingConstructor] + public BuildingProjectsProvider( + [Import(typeof(ISolutionProvider))] ISolutionProvider solutionProvider, + [Import(typeof(IBuildInformationProvider))] IBuildInformationProvider buildInformationProvider) + { + _projects = new ObservableCollection<ProjectItem>(); + _solutionProvider = solutionProvider; + _buildInformationProvider = buildInformationProvider; + } + + public void ReloadCurrentProjects() + { + _projects.Clear(); + _projects.AddRange(_solutionProvider.GetProjects()); + } + + public ObservableCollection<ProjectItem> GetBuildingProjects() + { + return _projects; + } + + public void ProjectBuildStarted(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, uint dwAction) + { + try + { + var projectItem = _projects.FirstOrDefault(item => ProjectIdentifierGenerator.GetIdentifierForProjectItem(item) == ProjectIdentifierGenerator.GetIdentifierForInteropTypes(pHierProj, pCfgProj)); + if (projectItem == null) + { + // In this case we are executing a batch build so we need to add the projectitem manually + projectItem = new UI.Models.ProjectItem(); + var configPair = pCfgProj.ToConfigurationTuple(); + SolutionProjectsExtensions.UpdateProperties(pHierProj.ToProject(), projectItem, configPair.Item1, configPair.Item2); + _projects.Add(projectItem); + } + + projectItem.State = GetProjectState(_buildInformationProvider.GetBuildInformationModel().BuildAction); + projectItem.BuildFinishTime = null; + projectItem.BuildStartTime = DateTime.Now; + + // _viewModel.OnBuildProjectBegin(); + //if (BuildScope == BuildScopes.BuildScopeSolution && + // (BuildAction == BuildActions.BuildActionBuild || + // BuildAction == BuildActions.BuildActionRebuildAll)) + //{ + // currentProject.BuildOrder = _viewModel.BuildProgressViewModel.CurrentQueuePosOfBuildingProject; + //} + //if (!_viewModel.ProjectsList.Contains(currentProject)) + // _viewModel.ProjectsList.Add(currentProject); + //else if (_viewModel.ControlSettings.GeneralSettings.FillProjectListOnBuildBegin) + // _viewModel.OnPropertyChanged(nameof(BuildVisionPaneViewModel.GroupedProjectsList)); + //_viewModel.CurrentProject = currentProject; + } + catch (Exception ex) + { + ex.TraceUnknownException(); + } + } + + private bool PlatformsIsEquals(string platformName1, string platformName2) + { + if (string.Compare(platformName1, platformName2, StringComparison.InvariantCultureIgnoreCase) == 0) + return true; + + // The ambiguity between Project.ActiveConfiguration.PlatformName and + // ProjectStartedEventArgs.ProjectPlatform in Microsoft.Build.Utilities.Logger + // (see BuildOutputLogger). + bool isAnyCpu1 = (platformName1 == "Any CPU" || platformName1 == "AnyCPU"); + bool isAnyCpu2 = (platformName2 == "Any CPU" || platformName2 == "AnyCPU"); + if (isAnyCpu1 && isAnyCpu2) + return true; + + return false; + } + + //public bool GetProjectItem(IBuildVisionPaneViewModel viewModel, BuildProjectContextEntry projectEntry, out ProjectItem projectItem) + //{ + // projectItem = projectEntry.ProjectItem; + // if (projectItem != null) + // return true; + + // string projectFile = projectEntry.FileName; + // if (ProjectExtensions.IsProjectHidden(projectFile)) + // return false; + + // var projectProperties = projectEntry.Properties; + // var project = viewModel.ProjectsList.FirstOrDefault(x => x.FullName == projectFile); + + + // if (projectProperties.ContainsKey("Configuration") && projectProperties.ContainsKey("Platform")) + // { + // string projectConfiguration = projectProperties["Configuration"]; + // string projectPlatform = projectProperties["Platform"]; + // projectItem = FindProjectItemInProjectsByUniqueName(viewModel, project.UniqueName, projectConfiguration, projectPlatform); + // if (projectItem == null) + // { + // TraceManager.Trace( + // string.Format("Project Item not found by: UniqueName='{0}', Configuration='{1}, Platform='{2}'.", + // project.UniqueName, + // projectConfiguration, + // projectPlatform), + // EventLogEntryType.Warning); + // return false; + // } + // } + // else + // { + // return false; + // } + + // projectEntry.ProjectItem = projectItem; + // return true; + //} + + private ProjectState GetProjectState(BuildActions buildAction) + { + switch (buildAction) + { + case BuildActions.BuildActionBuild: + case BuildActions.BuildActionRebuildAll: + return ProjectState.Building; + + case BuildActions.BuildActionClean: + return ProjectState.Cleaning; + + case BuildActions.BuildActionDeploy: + throw new InvalidOperationException("vsBuildActionDeploy not supported"); + + default: + throw new ArgumentOutOfRangeException(nameof(buildAction)); + } + } + + public void ProjectBuildFinished(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, bool succeess, bool canceled) + { + var currentProject = _projects.First(item => ProjectIdentifierGenerator.GetIdentifierForProjectItem(item) == ProjectIdentifierGenerator.GetIdentifierForInteropTypes(pHierProj, pCfgProj)); + currentProject.State = ProjectState.BuildDone; + //currentProject.Success = fSuccess == 1; + //ProjectState projectState; + //switch (SolutionBuildState.BuildAction) + //{ + // case BuildActions.BuildActionBuild: + // case BuildActions.BuildActionRebuildAll: + // if (currentProject.Success) + // { + // if (_viewModel.ControlSettings.GeneralSettings.ShowWarningSignForBuilds && buildedProject.ErrorsBox.WarningsCount > 0) + // projectState = ProjectState.BuildWarning; + // else + // { + // bool upToDate = (_buildLogger != null && _buildLogger.Projects != null + // && !_buildLogger.Projects.Exists(t => t.FileName == buildedProject.FileName)); + // if (upToDate) + // { + // // Because ErrorBox will be empty if project is UpToDate. + // buildedProject.ErrorsBox = currentProject.ErrorsBox; + // } + // projectState = upToDate ? ProjectState.UpToDate : ProjectState.BuildDone; + // } + // } + // else + // { + // bool canceled = (_buildCancelled && buildedProject.ErrorsBox.ErrorsCount == 0); + // projectState = canceled ? ProjectState.BuildCancelled : ProjectState.BuildError; + // } + // break; + + // case BuildActions.BuildActionClean: + // projectState = fSuccess == 1 ? ProjectState.CleanDone : ProjectState.CleanError; + // break; + + // case BuildActions.BuildActionDeploy: + // throw new InvalidOperationException("vsBuildActionDeploy not supported"); + + // default: + // throw new ArgumentOutOfRangeException(nameof(SolutionBuildState.BuildAction)); + //} + + //buildedProject.ProjectState = projectState; + //OnBuildProjectDone(new BuildProjectEventArgs(currentProject, projectState, eventTime, buildedProject)); + + //Debug.WriteLine($"UpdateProjectCfg_Done {proj.UniqueName} ({projConfiguration}) ({slnConfiguration}"); + + //if (e.ProjectState == ProjectState.BuildError && _viewModel.ControlSettings.GeneralSettings.StopBuildAfterFirstError) + // CancelBuildAsync(); + + //try + //{ + // ProjectItem currentProject = e.ProjectItem; + // currentProject.State = e.ProjectState; + // currentProject.BuildFinishTime = DateTime.Now; + // currentProject.UpdatePostBuildProperties(e.BuildedProjectInfo); + + // if (!_viewModel.ProjectsList.Contains(currentProject)) + // _viewModel.ProjectsList.Add(currentProject); + + // if (ReferenceEquals(_viewModel.CurrentProject, e.ProjectItem) && BuildingProjects.Any()) + // _viewModel.CurrentProject = BuildingProjects.Last(); + //} + //catch (Exception ex) + //{ + // ex.TraceUnknownException(); + //} + + //_viewModel.UpdateIndicators(this); + + //try + //{ + // _viewModel.OnBuildProjectDone(e.BuildedProjectInfo); + //} + //catch (Exception ex) + //{ + // ex.TraceUnknownException(); + //} + } + } +} diff --git a/src/BuildVision/Services/IBuildingProjectsProvider.cs b/src/BuildVision/Services/IBuildingProjectsProvider.cs new file mode 100644 index 00000000..13b8aa47 --- /dev/null +++ b/src/BuildVision/Services/IBuildingProjectsProvider.cs @@ -0,0 +1,14 @@ +using System.Collections.ObjectModel; +using BuildVision.UI.Models; +using Microsoft.VisualStudio.Shell.Interop; + +namespace BuildVision.Core +{ + public interface IBuildingProjectsProvider + { + ObservableCollection<ProjectItem> GetBuildingProjects(); + void ProjectBuildFinished(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, bool succeess, bool canceled); + void ProjectBuildStarted(IVsHierarchy pHierProj, IVsCfg pCfgProj, IVsCfg pCfgSln, uint dwAction); + void ReloadCurrentProjects(); + } +} diff --git a/src/BuildVision/Services/ISolutionProvider.cs b/src/BuildVision/Services/ISolutionProvider.cs new file mode 100644 index 00000000..a471d6b1 --- /dev/null +++ b/src/BuildVision/Services/ISolutionProvider.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using BuildVision.Contracts.Models; +using BuildVision.UI.Models; + +namespace BuildVision.Core +{ + public interface ISolutionProvider + { + ISolutionModel GetSolutionModel(); + void ReloadSolution(); + IEnumerable<ProjectItem> GetProjects(); + } +} diff --git a/src/BuildVision/Services/SolutionProvider.cs b/src/BuildVision/Services/SolutionProvider.cs new file mode 100644 index 00000000..2d78283a --- /dev/null +++ b/src/BuildVision/Services/SolutionProvider.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.IO; +using BuildVision.Contracts.Models; +using BuildVision.Exports.Services; +using BuildVision.Helpers; +using BuildVision.UI; +using BuildVision.UI.Common.Logging; +using BuildVision.UI.Models; +using EnvDTE; +using EnvDTE80; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; + +namespace BuildVision.Core +{ + [Export(typeof(IStatusBarNotificationService))] + [PartCreationPolicy(CreationPolicy.Shared)] + public class SolutionProvider : ISolutionProvider + { + private readonly IServiceProvider _serviceProvider; + private Solution _solution; + private SolutionModel _solutionModel; + private DTE2 _dte; + + [ImportingConstructor] + public SolutionProvider([Import(typeof(SVsServiceProvider))] IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public void ReloadSolution() + { + ThreadHelper.ThrowIfNotOnUIThread(); + _dte = _serviceProvider.GetService(typeof(DTE)) as DTE2; + _solution = _dte.Solution; + + RefrehSolutionModel(); + } + + public ISolutionModel GetSolutionModel() + { + return _solutionModel; + } + + private void RefrehSolutionModel() + { + if(_solutionModel == null) + _solutionModel = new SolutionModel(); + + try + { + if (_solution == null) + { + _solutionModel.Name = Resources.GridCellNATextInBrackets; + _solutionModel.FullName = Resources.GridCellNATextInBrackets; + _solutionModel.IsEmpty = true; + } + else if (string.IsNullOrEmpty(_solution.FileName)) + { + if (_solution.Count != 0 /* projects count */) + { + var project = _solution.Item(1); + _solutionModel.Name = Path.GetFileNameWithoutExtension(project.FileName); + _solutionModel.FullName = project.FullName; + _solutionModel.IsEmpty = false; + } + else + { + _solutionModel.Name = Resources.GridCellNATextInBrackets; + _solutionModel.FullName = Resources.GridCellNATextInBrackets; + _solutionModel.IsEmpty = true; + } + } + else + { + _solutionModel.Name = Path.GetFileNameWithoutExtension(_solution.FileName); + _solutionModel.FullName = _solution.FullName; + _solutionModel.IsEmpty = false; + } + } + catch (Exception ex) + { + ex.TraceUnknownException(); + _solutionModel.Name = Resources.GridCellNATextInBrackets; + _solutionModel.FullName = Resources.GridCellNATextInBrackets; + _solutionModel.IsEmpty = true; + } + } + + public IEnumerable<UI.Models.ProjectItem> GetProjects() + { + return _solution.GetProjectItems(); + } + } +} diff --git a/src/BuildVision/Core/StatusBarNotificationService.cs b/src/BuildVision/Services/StatusBarNotificationService.cs similarity index 100% rename from src/BuildVision/Core/StatusBarNotificationService.cs rename to src/BuildVision/Services/StatusBarNotificationService.cs