private void UpdateConfigurationForProject(IVsHierarchy project) { if (project == null) { return; } IEnumerable <CmdArgument> checkedArgs = ToolWindowViewModel.TreeViewModel.Projects.GetValueOrDefault(project.GetGuid())?.CheckedArguments; if (checkedArgs == null) { return; } IEnumerable <string> enabledEntries; if (IsMacroEvaluationEnabled) { enabledEntries = checkedArgs.Select( e => msBuildPropertyRegex.Replace(e.Value, match => vsHelper.GetMSBuildPropertyValue(project, match.Groups["propertyName"].Value) ?? match.Value)); } else { enabledEntries = checkedArgs.Select(e => e.Value); } string prjCmdArgs = string.Join(" ", enabledEntries); ProjectArguments.SetArguments(project, prjCmdArgs); Logger.Info($"Updated Configuration for Project: {project.GetName()}"); }
public string GetMSBuildPropertyValue(IVsHierarchy hierarchy, string propName) { var propStorage = hierarchy as IVsBuildPropertyStorage; if (propStorage == null) { return(null); } string configName; try { configName = hierarchy.GetProject()?.ConfigurationManager.ActiveConfiguration.ConfigurationName; } catch (Exception ex) { Logger.Warn($"Failed to get active configuration name for project '{hierarchy.GetName()}' with error '{ex}'"); return(null); } if (configName != null) { if (ErrorHandler.Succeeded(propStorage.GetPropertyValue(propName, configName, (int)_PersistStorageType.PST_PROJECT_FILE, out string value))) { return(value); } } return(null); }
private void DetachFsWatcherFromProject(IVsHierarchy project) { var guid = project.GetGuid(); if (projectFsWatchers.TryGetValue(guid, out FileSystemWatcher fsWatcher)) { fsWatcher.Dispose(); projectFsWatchers.Remove(guid); Logger.Info($"Detached FileSystemWatcher for project '{project.GetName()}'."); } }
private void UpdateConfigurationForProject(IVsHierarchy project) { if (project == null) { return; } var commandLineArgs = CreateCommandLineArgsForProject(project); if (commandLineArgs == null) { return; } ProjectArguments.SetArguments(project, commandLineArgs); Logger.Info($"Updated Configuration for Project: {project.GetName()}"); }
int IVsSolutionEvents4.OnAfterRenameProject(IVsHierarchy pHierarchy) { if (!ProjectArguments.IsSupportedProject(pHierarchy)) { return(LogIgnoringUnsupportedProjectType()); } Guid projectGuid = pHierarchy.GetGuid(); var oldProjectDir = ProjectStateMap[projectGuid].ProjectDir; var oldProjectName = ProjectStateMap[projectGuid].ProjectName; ProjectStateMap[projectGuid].ProjectDir = pHierarchy.GetProjectDir(); ProjectStateMap[projectGuid].ProjectName = pHierarchy.GetName(); ProjectAfterRename?.Invoke(this, new ProjectAfterRenameEventArgs { OldProjectDir = oldProjectDir, OldProjectName = oldProjectName, Project = pHierarchy }); return(S_OK); }
public string GetMSBuildPropertyValueForActiveConfig(IVsHierarchy hierarchy, string propName) { ThreadHelper.ThrowIfNotOnUIThread(); string configName = null; try { configName = hierarchy.GetProject()?.ConfigurationManager.ActiveConfiguration.ConfigurationName; } catch (Exception ex) { Logger.Warn($"Failed to get active configuration name for project '{hierarchy.GetName()}' with error '{ex}'"); return(null); } if (configName == null) { return(null); } return(GetMSBuildPropertyValue(hierarchy, propName, configName)); }
int IVsSolutionEvents.OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded) { if (!ProjectArguments.IsSupportedProject(pHierarchy)) { return(LogIgnoringUnsupportedProjectType()); } Guid projectGuid = pHierarchy.GetGuid(); string projectDir = pHierarchy.GetProjectDir(); string projectName = pHierarchy.GetName(); bool isLoaded = pHierarchy.IsLoaded(); bool isLoadProcess = ProjectStateMap.TryGetValue(projectGuid, out var state) && state.IsLoaded; ProjectStateMap[projectGuid] = new ProjectState { ProjectDir = projectDir, ProjectName = projectName, IsLoaded = isLoaded }; ProjectAfterOpen?.Invoke(this, new ProjectAfterOpenEventArgs { Project = pHierarchy, IsLoadProcess = isLoadProcess, IsSolutionOpenProcess = fAdded == 0 }); return(S_OK); }
private string FullFilenameForProjectJsonFileFromProject(IVsHierarchy project) { var userFilename = vsHelper.GetMSBuildPropertyValue(project, "SmartCmdArgJsonFile"); if (!string.IsNullOrEmpty(userFilename)) { // It's recommended to use absolute paths for the json file in the first place... userFilename = Path.GetFullPath(userFilename); // ... but make it absolute in any case. Logger.Info($"'SmartCmdArgJsonFile' msbuild property present in project '{project.GetName()}' will use json file '{userFilename}'."); return(userFilename); } else { return(FullFilenameForProjectJsonFileFromProjectPath(project.GetProjectDir(), project.GetName())); } }
private void UpdateCommandsForProject(IVsHierarchy project) { if (project == null) { throw new ArgumentNullException(nameof(project)); } Logger.Info($"Update commands for project '{project?.GetName()}'. IsVcsSupportEnabled={IsVcsSupportEnabled}. SolutionData.Count={toolWindowStateLoadedFromSolution?.ProjectArguments?.Count}."); var projectGuid = project.GetGuid(); if (projectGuid == Guid.Empty) { Logger.Info("Skipping project because guid euqals empty."); return; } var solutionData = toolWindowStateLoadedFromSolution ?? new ToolWindowStateSolutionData(); ToolWindowViewModel.TreeViewModel.ShowAllProjects = solutionData.ShowAllProjects; // joins data from solution and project // => overrides solution commands for a project if a project json file exists // => keeps all data from the suo file for projects without a json // => if we have data in our ViewModel we use this instad of the suo file // get project json data ToolWindowStateProjectData projectData = null; if (IsVcsSupportEnabled) { string filePath = FullFilenameForProjectJsonFileFromProject(project); if (File.Exists(filePath)) { try { using (Stream fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read)) { projectData = Logic.ToolWindowProjectDataSerializer.Deserialize(fileStream); } Logger.Info($"Read {projectData?.Items?.Count} commands for project '{project.GetName()}' from json-file '{filePath}'."); } catch (Exception e) { Logger.Warn($"Failed to read file '{filePath}' with error '{e}'."); projectData = null; } } else { Logger.Info($"Json-file '{filePath}' doesn't exists."); } } // project json overrides if it exists if (projectData != null) { Logger.Info($"Setting {projectData?.Items?.Count} commands for project '{project.GetName()}' from json-file."); var projectListViewModel = ToolWindowViewModel.TreeViewModel.Projects.GetValueOrDefault(projectGuid); // update enabled state of the project json data (source prio: ViewModel > suo file) if (projectData.Items != null) { var argumentDataFromProject = projectData.AllArguments; var argumentDataFromLVM = projectListViewModel?.AllArguments.ToDictionary(arg => arg.Id, arg => arg); foreach (var dataFromProject in argumentDataFromProject) { if (argumentDataFromLVM != null && argumentDataFromLVM.TryGetValue(dataFromProject.Id, out CmdArgument argFromVM)) { dataFromProject.Enabled = argFromVM.IsChecked; } else { dataFromProject.Enabled = solutionData.CheckedArguments.Contains(dataFromProject.Id); } } var containerDataFromProject = projectData.AllContainer; var containerDataFromLVM = projectListViewModel?.AllContainer.ToDictionary(con => con.Id, con => con); foreach (var dataFromProject in containerDataFromProject) { if (containerDataFromLVM != null && containerDataFromLVM.TryGetValue(dataFromProject.Id, out CmdContainer conFromVM)) { dataFromProject.Expanded = conFromVM.IsExpanded; } else { dataFromProject.Expanded = solutionData.ExpandedContainer.Contains(dataFromProject.Id); } } if (projectListViewModel != null) { projectData.Expanded = projectListViewModel.IsExpanded; } else { projectData.Expanded = solutionData.ExpandedContainer.Contains(projectData.Id); } } else { projectData = new ToolWindowStateProjectData(); Logger.Info($"DataCollection for project '{project.GetName()}' is null."); } } // if we have data in the ViewModel we keep it else if (ToolWindowViewModel.TreeViewModel.Projects.ContainsKey(projectGuid)) { return; } else if (IsVcsSupportEnabled) { projectData = new ToolWindowStateProjectData(); Logger.Info("Will clear all data because of missing json file and enabled VCS support."); } // we try to read the suo file data else if (solutionData.ProjectArguments.TryGetValue(projectGuid, out projectData)) { Logger.Info($"Will use commands from suo file for project '{project.GetName()}'."); var argumentDataFromProject = projectData.AllArguments; foreach (var arg in argumentDataFromProject) { arg.Enabled = solutionData.CheckedArguments.Contains(arg.Id); } var containerDataFromProject = projectData.AllContainer; foreach (var con in containerDataFromProject) { con.Expanded = solutionData.ExpandedContainer.Contains(con.Id); } projectData.Expanded = solutionData.ExpandedContainer.Contains(projectData.Id); } else { Logger.Info($"Gathering commands from configurations for project '{project.GetName()}'."); // if we don't have suo file data we read cmd args from the project configs projectData = new ToolWindowStateProjectData(); projectData.Items.AddRange( ReadCommandlineArgumentsFromProject(project) .Select(cmdLineArg => new ListEntryData { Command = cmdLineArg })); } // push projectData to the ViewModel ToolWindowViewModel.PopulateFromProjectData(project, projectData); Logger.Info($"Updated Commands for project '{project.GetName()}'."); }
private void AttachFsWatcherToProject(IVsHierarchy project) { string realProjectJsonFileFullName = SymbolicLinkUtils.GetRealPath(FullFilenameForProjectJsonFileFromProject(project)); try { var projectJsonFileWatcher = new FileSystemWatcher(); projectJsonFileWatcher.Path = Path.GetDirectoryName(realProjectJsonFileFullName); projectJsonFileWatcher.Filter = Path.GetFileName(realProjectJsonFileFullName); projectJsonFileWatcher.EnableRaisingEvents = true; projectFsWatchers.Add(project.GetGuid(), projectJsonFileWatcher); projectJsonFileWatcher.Changed += (fsWatcher, args) => { Logger.Info($"SystemFileWatcher file Change '{args.FullPath}'"); if (IsVcsSupportEnabled) { UpdateCommandsForProjectOnDispatcher(project); } }; projectJsonFileWatcher.Created += (fsWatcher, args) => { Logger.Info($"SystemFileWatcher file Created '{args.FullPath}'"); if (IsVcsSupportEnabled) { UpdateCommandsForProjectOnDispatcher(project); } }; projectJsonFileWatcher.Renamed += (fsWatcher, args) => { Logger.Info($"FileWachter file Renamed '{args.FullPath}'. realProjectJsonFileFullName='{realProjectJsonFileFullName}'"); if (IsVcsSupportEnabled && realProjectJsonFileFullName == args.FullPath) { UpdateCommandsForProjectOnDispatcher(project); } }; Logger.Info($"Attached FileSystemWatcher to file '{realProjectJsonFileFullName}' for project '{project.GetName()}'."); } catch (Exception e) { Logger.Warn($"Failed to attach FileSystemWatcher to file '{realProjectJsonFileFullName}' for project '{project.GetName()}' with error '{e}'."); } }
private void UpdateCommandsForProject(IVsHierarchy project) { if (project == null) { throw new ArgumentNullException(nameof(project)); } Logger.Info($"Update commands for project '{project?.GetName()}'. IsVcsSupportEnabled={IsVcsSupportEnabled}. SolutionData.Count={toolWindowStateLoadedFromSolution?.ProjectArguments?.Count}."); var projectGuid = project.GetGuid(); if (projectGuid == Guid.Empty) { Logger.Info("Skipping project because guid euqals empty."); return; } var solutionData = toolWindowStateLoadedFromSolution ?? new SuoDataJson(); // joins data from solution and project // => overrides solution commands for a project if a project json file exists // => keeps all data from the suo file for projects without a json // => if we have data in our ViewModel we use this instad of the suo file // get project json data ProjectDataJson projectData = null; if (IsVcsSupportEnabled) { projectData = fileStorage.ReadDataForProject(project); } // project json overrides if it exists if (projectData != null) { Logger.Info($"Setting {projectData?.Items?.Count} commands for project '{project.GetName()}' from json-file."); var projectListViewModel = ToolWindowViewModel.TreeViewModel.Projects.GetValueOrDefault(projectGuid); var projHasSuoData = solutionData.ProjectArguments.ContainsKey(projectGuid); // update enabled state of the project json data (source prio: ViewModel > suo file) if (projectData.Items != null) { var argumentDataFromProject = projectData.AllArguments; var argumentDataFromLVM = projectListViewModel?.AllArguments.ToDictionary(arg => arg.Id, arg => arg); foreach (var dataFromProject in argumentDataFromProject) { if (argumentDataFromLVM != null && argumentDataFromLVM.TryGetValue(dataFromProject.Id, out CmdArgument argFromVM)) { dataFromProject.Enabled = argFromVM.IsChecked; } else if (projHasSuoData) { dataFromProject.Enabled = solutionData.CheckedArguments.Contains(dataFromProject.Id); } else { dataFromProject.Enabled = dataFromProject.DefaultChecked; } } var containerDataFromProject = projectData.AllContainer; var containerDataFromLVM = projectListViewModel?.AllContainer.ToDictionary(con => con.Id, con => con); foreach (var dataFromProject in containerDataFromProject) { if (containerDataFromLVM != null && containerDataFromLVM.TryGetValue(dataFromProject.Id, out CmdContainer conFromVM)) { dataFromProject.Expanded = conFromVM.IsExpanded; } else { dataFromProject.Expanded = solutionData.ExpandedContainer.Contains(dataFromProject.Id); } } var itemDataFromProject = projectData.AllItems; var itemDataFromLVM = projectListViewModel?.ToDictionary(item => item.Id, item => item); foreach (var dataFromProject in itemDataFromProject) { if (itemDataFromLVM != null && itemDataFromLVM.TryGetValue(dataFromProject.Id, out CmdBase itemFromVM)) { dataFromProject.Selected = itemFromVM.IsSelected; } else { dataFromProject.Selected = solutionData.SelectedItems.Contains(dataFromProject.Id); } } if (projectListViewModel != null) { projectData.Expanded = projectListViewModel.IsExpanded; projectData.Selected = projectListViewModel.IsSelected; } else { projectData.Expanded = solutionData.ExpandedContainer.Contains(projectData.Id); projectData.Selected = solutionData.SelectedItems.Contains(projectData.Id); } } else { projectData = new ProjectDataJson(); Logger.Info($"DataCollection for project '{project.GetName()}' is null."); } } // if we have data in the ViewModel we keep it else if (ToolWindowViewModel.TreeViewModel.Projects.ContainsKey(projectGuid)) { return; } else if (IsVcsSupportEnabled) { projectData = new ProjectDataJson(); Logger.Info("Will clear all data because of missing json file and enabled VCS support."); } // we try to read the suo file data else if (solutionData.ProjectArguments.TryGetValue(projectGuid, out projectData)) { Logger.Info($"Will use commands from suo file for project '{project.GetName()}'."); var argumentDataFromProject = projectData.AllArguments; foreach (var arg in argumentDataFromProject) { arg.Enabled = solutionData.CheckedArguments.Contains(arg.Id); } var containerDataFromProject = projectData.AllContainer; foreach (var con in containerDataFromProject) { con.Expanded = solutionData.ExpandedContainer.Contains(con.Id); } var itemDataFromProject = projectData.AllItems; foreach (var item in itemDataFromProject) { item.Selected = solutionData.SelectedItems.Contains(item.Id); } projectData.Expanded = solutionData.ExpandedContainer.Contains(projectData.Id); projectData.Selected = solutionData.SelectedItems.Contains(projectData.Id); } else { Logger.Info($"Gathering commands from configurations for project '{project.GetName()}'."); // if we don't have suo file data we read cmd args from the project configs projectData = new ProjectDataJson(); projectData.Items.AddRange(ReadCommandlineArgumentsFromProject(project)); } // push projectData to the ViewModel ToolWindowViewModel.PopulateFromProjectData(project, projectData); Logger.Info($"Updated Commands for project '{project.GetName()}'."); }
public ProjectDataJson ReadDataForProject(IVsHierarchy project) { ProjectDataJson result = null; if (!cmdPackage.IsUseSolutionDirEnabled) { string filePath = FullFilenameForProjectJsonFileFromProject(project); if (File.Exists(filePath)) { try { using (Stream fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read)) { result = Logic.ProjectDataSerializer.Deserialize(fileStream); } Logger.Info($"Read {result?.Items?.Count} commands for project '{project.GetName()}' from json-file '{filePath}'."); } catch (Exception e) { Logger.Warn($"Failed to read file '{filePath}' with error '{e}'."); result = null; } } else { Logger.Info($"Json-file '{filePath}' doesn't exists."); } return(result); } else { Guid projectGui = project.GetGuid(); string slnFilename = vsHelper.GetSolutionFilename(); string jsonFilename = Path.ChangeExtension(slnFilename, "args.json"); if (File.Exists(jsonFilename)) { try { using (Stream fileStream = File.Open(jsonFilename, FileMode.Open, FileAccess.Read)) { SolutionDataJson slnData = SolutionDataSerializer.Deserialize(fileStream); result = slnData.ProjectArguments.FirstOrDefault(p => p.Id == projectGui); } Logger.Info($"Read {result?.Items?.Count} commands for project '{project.GetName()}' from json-file '{jsonFilename}'."); } catch (Exception e) { Logger.Warn($"Failed to read file '{jsonFilename}' with error '{e}'."); result = null; } } else { Logger.Info($"Json-file '{jsonFilename}' doesn't exists."); } return(result); } }