logic: vs plugin multithreading

added simple multithreading for cdb creation
This commit is contained in:
Manuel Dobusch
2017-02-02 17:03:52 +01:00
parent 52b0cd2017
commit 8c0f9f2de4
37 changed files with 64356 additions and 171 deletions
+11
View File
@@ -0,0 +1,11 @@
------------
Dependencies
------------
Json.NET
-Install
-Rightclick on 'References'
-Click 'Manage NuGet Packages'
-Search 'json'
-Install 'Newtsoft.Json'
Binary file not shown.
@@ -61,6 +61,10 @@
<Reference Include="Microsoft.VisualStudio.VCProjectEngine, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
@@ -136,6 +140,9 @@
<Compile Include="Logging\LogMessage.cs" />
<Compile Include="Logging\Obfuscation\NameObfuscator.cs" />
<Compile Include="Logging\VSOutputLogger.cs" />
<Compile Include="Multitasking\LimitedThreadsTaskScheduler.cs" />
<Compile Include="Utility\CompilationDatabaseList.cs" />
<Compile Include="Utility\DataUtility.cs" />
<Compile Include="Utility\FileUtility.cs" />
<Compile Include="Guids.cs" />
<Compile Include="Utility\NetworkProtocolUtility.cs" />
@@ -201,6 +208,7 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
@@ -32,7 +32,7 @@
<Groups>
<Group guid="guidCoatiPluginCmdSet" id="MyMenuGroup" priority="0x0600">
<Group guid="guidCoatiPluginCmdSet" id="ContextMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>
</Group>
@@ -44,37 +44,23 @@
<Parent guid="guidCoatiPluginCmdSet" id="TopLevelMenu"/>
</Group>
<!--
<Group guid="guidCoatiPluginCmdSet" id="HelpMenu" priority="0x0600">
<Parent guid="guidCoatiPluginCmdSet" id="TopLevelMenu"/>
</Group>
-->
</Groups>
<Buttons>
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiSetActiveToken" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="MyMenuGroup" />
<Parent guid="guidCoatiPluginCmdSet" id="ContextMenuGroup" />
<Icon guid="icon" id="icon0" />
<Strings>
<ButtonText>Set active Token</ButtonText>
</Strings>
</Button>
<!--
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiCreateProject" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="MyMenuGroup" />
<Icon guid="icon" id="icon0" />
<Strings>
<ButtonText>Create Coati Project</ButtonText>
</Strings>
</Button>
-->
<!--
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiCreateProject" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="SubMenu" />
<Icon guid="icon" id="icon0" />
<Strings>
<ButtonText>Create Coati Project</ButtonText>
</Strings>
</Button>
-->
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiCreateCDB" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="SubMenu" />
@@ -83,18 +69,45 @@
<ButtonText>Create CDB</ButtonText>
</Strings>
</Button>
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiOpenLogFolder" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="SubMenu" />
<Strings>
<ButtonText>Open Log Directory</ButtonText>
</Strings>
</Button>
<!--
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiHelp" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="HelpMenu" />
<Strings>
<ButtonText>Online Help</ButtonText>
</Strings>
</Button>
-->
</Buttons>
<Menus>
<Menu guid="guidCoatiPluginCmdSet" id="TopLevelMenu" priority="0x700" type="Menu">
<Parent guid="guidSHLMainMenu"
id="IDG_VS_MM_TOOLSADDINS"/>
<Parent guid="guidSHLMainMenu" id="IDG_VS_MM_TOOLSADDINS"/>
<Strings>
<ButtonText>Coati</ButtonText>
<CommandName>Coati</CommandName>
</Strings>
</Menu>
<!--
<Menu guid="guidCoatiPluginCmdSet" id="HelpMenu" priority="0x700" type="Menu">
<Parent guid="guidCoatiPluginCmdSet" id="TopLevelMenu"/>
<Strings>
<ButtonText>Coati Help</ButtonText>
<CommandName>Coati Help</CommandName>
</Strings>
</Menu>
-->
</Menus>
</Commands>
@@ -110,7 +123,7 @@
<!-- This is the guid used to group the menu commands together -->
<GuidSymbol name="guidCoatiPluginCmdSet" value="{0efb005b-715c-4a62-8a9b-1e5a870e6c34}">
<IDSymbol name="MyMenuGroup" value="0x1020" />
<IDSymbol name="ContextMenuGroup" value="0x1020" />
<IDSymbol name="cmdidCoatiPing" value="0x0100" />
<IDSymbol name="cmdidCoatiFile" value="0x0101"/>
<IDSymbol name="cmdidCoatiGetActiveFileName" value="0x0102"/>
@@ -118,8 +131,11 @@
<IDSymbol name="cmdidCoatiSetActiveToken" value="0x0104"/>
<IDSymbol name="cmdidCoatiCreateProject" value="0x0105"/>
<IDSymbol name="cmdidCoatiCreateCDB" value="0x0106"/>
<IDSymbol name="cmdidCoatiOpenLogFolder" value="0x0107"/>
<IDSymbol name="TopLevelMenu" value="0x1021"/>
<IDSymbol name="SubMenu" value="0x1022"/>
<IDSymbol name="HelpMenu" value="0x1023"/>
<IDSymbol name="cmdidCoatiHelp" value="0x1024"/>
</GuidSymbol>
@@ -19,12 +19,14 @@ namespace CoatiSoftware.CoatiPlugin
private uint _clientPort = 6667;
private bool _logging = false;
private bool _obfuscateLogging = false;
private uint _threadCount = 1;
public delegate void Callback();
public static Callback _serverPortChangeCallback = null;
public static Callback _clientPortChangeCallback = null;
public static Callback _loggingToggled = null;
public static Callback _obfuscationToggled = null;
public static Callback _threadCountChanged = null;
[Category("Coati")]
[DisplayName("VS Port")]
@@ -90,6 +92,22 @@ namespace CoatiSoftware.CoatiPlugin
}
}
[Category("Coati")]
[DisplayName("Thread Count")]
[Description("The maximum number of threads that will be used while building Compilation Databases")]
public uint ThreadCount
{
get { return _threadCount; }
set
{
_threadCount = value;
if(_threadCountChanged != null)
{
_threadCountChanged();
}
}
}
public OptionPageGrid()
{
}
@@ -107,11 +125,14 @@ namespace CoatiSoftware.CoatiPlugin
private MenuCommand _menuItemSetActiveToken = null;
private MenuCommand _menuItemCreateProject = null;
private MenuCommand _menuItemCreateCDB = null;
private MenuCommand _menuItemOpenLogDir = null;
private SolutionEvents _solutionEvents = null;
private bool _validSolutionLoaded = false;
Utility.CompilationDatabaseList _cdbList = new Utility.CompilationDatabaseList();
public uint ServerPort
{
get
@@ -148,6 +169,15 @@ namespace CoatiSoftware.CoatiPlugin
}
}
public uint ThreadCount
{
get
{
OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
return page.ThreadCount;
}
}
System.Threading.Thread _serverThread = null;
@@ -177,18 +207,22 @@ namespace CoatiSoftware.CoatiPlugin
CommandID setActiveTokenCommandID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiSetActiveToken);
CommandID createProjectID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiCreateProject);
CommandID createCDBID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiCreateCDB);
CommandID openLogDirID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiOpenLogFolder);
_menuItemSetActiveToken = new MenuCommand(MenuItemCallback, setActiveTokenCommandID);
_menuItemCreateProject = new MenuCommand(MenuItemCallback, createProjectID);
_menuItemCreateCDB = new MenuCommand(MenuItemCallback, createCDBID);
_menuItemOpenLogDir = new MenuCommand(MenuItemCallback, openLogDirID);
_menuItemCreateProject.Enabled = false;
_menuItemSetActiveToken.Enabled = false;
_menuItemCreateCDB.Enabled = false;
_menuItemOpenLogDir.Enabled = true;
mcs.AddCommand(_menuItemSetActiveToken);
mcs.AddCommand(_menuItemCreateProject);
mcs.AddCommand(_menuItemCreateCDB);
mcs.AddCommand(_menuItemOpenLogDir);
}
// register callbacks to enable/disable interaction for eligible solutions
@@ -213,6 +247,13 @@ namespace CoatiSoftware.CoatiPlugin
DTE dte = (DTE)GetService(typeof(DTE));
List<String> languages = Utility.SolutionUtility.GetSolutionLanguages(dte);
string solutionPath = Utility.SolutionUtility.GetSolutionPath(dte);
if(_cdbList.CheckCDBForSolutionExists(solutionPath))
{
Logging.Logging.LogInfo("A CDB for the loaded solution already exists.");
}
bool enable = false;
foreach (String language in languages)
{
@@ -298,6 +339,8 @@ namespace CoatiSoftware.CoatiPlugin
private void OnCreateProject(List<EnvDTE.Project> projects, string configurationName, string platformName, string targetDir, string fileName, string cStandard)
{
DTE dte = (DTE)GetService(typeof(DTE));
Wizard.WindowCreateCDB createCDB = new Wizard.WindowCreateCDB();
createCDB.Projects = projects;
createCDB.ConfigurationName = configurationName;
@@ -305,6 +348,10 @@ namespace CoatiSoftware.CoatiPlugin
createCDB.TargetDir = targetDir;
createCDB.FileName = fileName;
createCDB.CStandard = cStandard;
createCDB.ThreadCount = (int)ThreadCount;
createCDB.SolutionDir = Utility.SolutionUtility.GetSolutionPath(dte);
createCDB.CDB = _cdbList.GetCDBForSolution(createCDB.SolutionDir, targetDir + "\\" + fileName + ".json");
createCDB.CallbackOnFinishedCreatingCDB = HandleFinishedCDB;
@@ -316,7 +363,15 @@ namespace CoatiSoftware.CoatiPlugin
{
if(creationResult._cdb != null && creationResult._cdbDirectory.Length > 0 && creationResult._cdbName.Length > 0)
{
if(WriteCDBToFile(creationResult._cdb, creationResult._cdbDirectory, creationResult._cdbName))
_cdbList.Append(creationResult._cdb);
_cdbList.SaveMetaData();
// string metaData = creationResult._cdb.SerializeMetaDataXML();
// Utility.DataUtility.GetInstance().AppendData(metaData);
if (WriteCDBToFile(creationResult._cdb, creationResult._cdbDirectory, creationResult._cdbName))
{
string title = "CDB finished";
string text = "The CDB '" + creationResult._cdbName + "' was created at directory \"" + creationResult._cdbDirectory + "\"\n";
@@ -330,6 +385,8 @@ namespace CoatiSoftware.CoatiPlugin
Utility.AsynchronousClient.Send(message);
}
_cdbList.Refresh();
}
else
{
@@ -367,12 +424,16 @@ namespace CoatiSoftware.CoatiPlugin
Logging.Logging.LogError(text);
Logging.Logging.LogError("Exception: " + e.Message);
_cdbList.UnloadCDBs();
return false;
}
string message = "The CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' was created at directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n";
Logging.Logging.LogInfo(message);
_cdbList.UnloadCDBs();
return true;
}
@@ -410,6 +471,10 @@ namespace CoatiSoftware.CoatiPlugin
windowMessage.RefreshWindow();
windowMessage.ShowDialog();
}
else if(menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidCoatiOpenLogFolder)
{
Utility.SystemUtility.OpenWindowsExplorerAtDirectory(Utility.DataUtility.GetStandardFolderDirectory());
}
}
}
@@ -559,22 +624,24 @@ namespace CoatiSoftware.CoatiPlugin
Utility.SolutionUtility.SolutionStructure projectStructure = Utility.SolutionUtility.GetSolutionVCProjects(dte);
List<List<string>> configsAndPlatforms = Utility.SolutionUtility.GetConfigurationAndPlatformNames(dte);
window.m_projectStructure = projectStructure;
window._projectStructure = projectStructure;
window.m_configurations = configsAndPlatforms[0];
window.m_platforms = configsAndPlatforms[1];
window._configurations = configsAndPlatforms[0];
window._platforms = configsAndPlatforms[1];
string directory = System.IO.Path.GetDirectoryName(dte.Solution.FullName);
window.m_solutionDirectory = directory;
window._solutionDirectory = directory;
string solutionName = System.IO.Path.GetFileNameWithoutExtension(dte.Solution.FullName);
window.m_solutionFileName = solutionName;
window._solutionFileName = solutionName;
bool containsCFiles = true; // Utility.SolutionUtility.ContainsCFiles(dte); // takes ridiculously long, I'd rather just display the option by default
window.m_containsCFiles = containsCFiles;
window._containsCFiles = containsCFiles;
window._cdb = _cdbList.GetMostCurrentCDBForSolution(Utility.SolutionUtility.GetSolutionPath(dte));
window.UpdateGUI();
window.m_onCreateProject = OnCreateProject;
window._onCreateProject = OnCreateProject;
window.ShowDialog();
}
@@ -0,0 +1,138 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// based on: https://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler(v=vs.110).aspx
namespace CoatiSoftware.CoatiPlugin.Multitasking
{
class LimitedThreadsTaskScheduler : TaskScheduler
{
[ThreadStatic]
private static bool _currentThreadIsProcessingItems;
private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
private readonly int _maxNumberOfRunningThreads = 0;
private int _delegatesQueuedOrRunning = 0;
public LimitedThreadsTaskScheduler(int maxNumberOfRunningThreads)
{
if (maxNumberOfRunningThreads < 1)
{
maxNumberOfRunningThreads = 1;
}
_maxNumberOfRunningThreads = maxNumberOfRunningThreads;
}
protected override IEnumerable<Task> GetScheduledTasks()
{
bool lockTaken = false;
try
{
Monitor.TryEnter(_tasks, ref lockTaken);
if(lockTaken)
{
return _tasks;
}
else
{
throw new NotSupportedException();
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(_tasks);
}
}
}
protected override void QueueTask(Task task)
{
lock(_tasks)
{
_tasks.AddLast(task);
if(_delegatesQueuedOrRunning < _maxNumberOfRunningThreads)
{
++_delegatesQueuedOrRunning;
NotifyThreadPoolOfPendingWork();
}
}
}
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
if(!_currentThreadIsProcessingItems)
{
return false;
}
if(taskWasPreviouslyQueued)
{
if(TryDequeue(task))
{
return base.TryExecuteTask(task);
}
else
{
return false;
}
}
else
{
return base.TryExecuteTask(task);
}
}
private void NotifyThreadPoolOfPendingWork()
{
ThreadPool.UnsafeQueueUserWorkItem(_ =>
{
_currentThreadIsProcessingItems = true;
try
{
while(true)
{
Task item;
lock(_tasks)
{
if(_tasks.Count <= 0)
{
--_delegatesQueuedOrRunning;
break;
}
item = _tasks.First.Value;
_tasks.RemoveFirst();
}
base.TryExecuteTask(item);
}
}
finally
{
_currentThreadIsProcessingItems = false;
}
}, null);
}
protected sealed override bool TryDequeue(Task task)
{
lock(_tasks)
{
return _tasks.Remove(task);
}
}
}
}
@@ -9,5 +9,7 @@ namespace CoatiSoftware.CoatiPlugin
public const uint cmdidCoatiSetActiveToken = 0x104;
public const uint cmdidCoatiCreateProject = 0x105;
public const uint cmdidCoatiCreateCDB = 0x106;
public const uint cmdidCoatiOpenLogFolder = 0x107;
};
}
@@ -10,7 +10,13 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
public string File
{
get { return _file; }
set { _file = value; }
set
{
_file = value;
//_file = _file.Replace('"', '\'');
//_file = _file.Replace('\"', '\'');
//_file = _file.Replace("\\\"", "'");
}
}
public string Directory
@@ -22,16 +28,22 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
public string Command
{
get { return _command; }
set { _command = value; }
set
{
_command = value;
//_command = _command.Replace('"', '\'');
//_command = _command.Replace("\"", "'");
//_command = _command.Replace("\\\"", "'");
}
}
public string SerializeJSON()
{
string result = "\t{\n";
result += "\t\t\"directory\": \"" + _directory + "\",\n";
result += "\t\t\"command\": \"" + _command + "\",\n";
result += "\t\t\"file\": \"" + _file + "\"\n";
result += "\t\t\"directory\": \"" + Directory + "\",\n";
result += "\t\t\"command\": \"" + Command + "\",\n";
result += "\t\t\"file\": \"" + File + "\"\n";
result += "\t}";
@@ -1,4 +1,7 @@
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Xml;
using Newtonsoft.Json.Linq;
namespace CoatiSoftware.CoatiPlugin.SolutionParser
{
@@ -6,9 +9,151 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
{
private List<CommandObject> _commandObjects = new List<CommandObject>();
public void AddCommandObject(CommandObject commandObject)
// meta data
private string _name = "";
private string _sourceProject = "";
private string _directory = "";
private System.DateTime _lastUpdated = new System.DateTime();
private List<string> _includedProjects = new List<string>();
private string _configurationName = "";
private string _platformName = "";
public string Name
{
_commandObjects.Add(commandObject);
get { return _name; }
set { _name = value; }
}
public string SourceProject
{
get { return _sourceProject; }
set { _sourceProject = value; }
}
public string Directory
{
get { return _directory; }
set { _directory = value; }
}
public System.DateTime LastUpdated
{
get { return _lastUpdated; }
set { _lastUpdated = value; }
}
public List<string> IncludedProjects
{
get { return _includedProjects; }
set { _includedProjects = value; }
}
public string ConfigurationName
{
get { return _configurationName; }
set { _configurationName = value; }
}
public string PlatformName
{
get { return _platformName; }
set { _platformName = value; }
}
public void AddOrUpdateCommandObject(CommandObject commandObject)
{
if (TryUpdateCommandObject(commandObject) == false)
{
_commandObjects.Add(commandObject);
}
}
// remove commandObjects for removed files
public void Clean()
{
for (int i = 0; i < _commandObjects.Count; i++)
{
if (System.IO.File.Exists(_commandObjects[i].File) == false)
{
_commandObjects.RemoveAt(i);
i--;
}
}
}
public void ClearCommandObjects()
{
_commandObjects.Clear();
}
public bool CheckCDBExists()
{
if (_directory.Length > 0 && _name.Length > 0)
{
string path = GetFilePath();
if(System.IO.File.Exists(path) == false)
{
_lastUpdated = System.DateTime.MinValue; // if file is missing, set date way back so it doesn't interfere with re-building
return false;
}
else
{
return true;
}
}
else
{
Logging.Logging.LogWarning("Can't check cdb data, directory and/or name has not been set: directory - '" + _directory + "', name - '" + _name + "'");
}
return false;
}
public bool TryLoadData()
{
if(_directory.Length > 0 && _name.Length > 0)
{
string path = GetFilePath();
if(System.IO.File.Exists(path))
{
string data = "";
using (System.IO.StreamReader file = new System.IO.StreamReader(path))
{
string line = "";
while ((line = file.ReadLine()) != null)
{
data += line;
}
}
DeserializeJSON(data);
return true;
}
else
{
_lastUpdated = System.DateTime.MinValue; // if file is missing, set date way back so it doesn't interfere with re-building
Logging.Logging.LogError("The cdb file '" + path + "' does not exist.");
}
}
else
{
Logging.Logging.LogWarning("Can't load cdb data, directory and/or name has not been set: directory - '" + _directory + "', name - '" + _name + "'");
}
return false;
}
public void UnloadData()
{
_commandObjects.Clear();
}
public string SerializeJSON()
@@ -24,5 +169,178 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
return result;
}
private void DeserializeJSON(string jsonCDB)
{
if(jsonCDB.Length > 0)
{
JArray commandObjects = JArray.Parse(jsonCDB);
_commandObjects.Clear();
foreach (JObject o in commandObjects.Children<JObject>())
{
CommandObject co = new CommandObject();
string directory = o.Property("directory").Value.ToString();
string command = o.Property("command").Value.ToString();
string file = o.Property("file").Value.ToString();
co.Directory = directory;
co.Command = command;
co.File = file;
_commandObjects.Add(co);
}
}
}
public XmlNode GetMetaDataXML(XmlDocument doc)
{
// XmlDocument doc = new XmlDocument();
XmlNode root = doc.CreateElement("cdb");
XmlElement name = doc.CreateElement("name");
name.InnerText = _name;
XmlElement sourceProject = doc.CreateElement("sourceProject");
sourceProject.InnerText = _sourceProject;
XmlElement directory = doc.CreateElement("directory");
directory.InnerText = _directory;
XmlElement lastUpdated = doc.CreateElement("lastUpdated");
lastUpdated.InnerText = _lastUpdated.ToString();
XmlElement includedProjects = doc.CreateElement("includedProjects");
foreach (string project in _includedProjects)
{
XmlElement includedProject = doc.CreateElement("includedProject");
includedProject.InnerText = project;
includedProjects.AppendChild(includedProject);
}
XmlElement configuration = doc.CreateElement("configuration");
configuration.InnerText = _configurationName;
XmlElement platform = doc.CreateElement("platform");
platform.InnerText = _platformName;
root.AppendChild(name);
root.AppendChild(sourceProject);
root.AppendChild(directory);
root.AppendChild(lastUpdated);
root.AppendChild(includedProjects);
root.AppendChild(configuration);
root.AppendChild(platform);
return root;
}
public string SerializeMetaDataXML()
{
XmlDocument doc = new XmlDocument();
XmlNode root = GetMetaDataXML(doc);
System.IO.StringWriter writer = new System.IO.StringWriter();
XmlSerializer serializer = new XmlSerializer(typeof(XmlElement));
serializer.Serialize(writer, root);
return writer.ToString();
}
public static List<CompilationDatabase> ParseCDBsMetaData(string data)
{
List<CompilationDatabase> cdbs = new List<CompilationDatabase>();
if(data.Length > 0)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(data);
XmlNode root = doc.SelectSingleNode("cdbs");
XmlNodeList nodes = root.SelectNodes("cdb");
foreach (XmlNode node in nodes)
{
cdbs.Add(ParseCDBMetaData(node));
}
}
return cdbs;
}
public static CompilationDatabase ParseCDBMetaData(XmlNode node)
{
CompilationDatabase cdb = new CompilationDatabase();
XmlNode nameNode = node.SelectSingleNode("name");
string name = nameNode.InnerText;
XmlNode sourceNode = node.SelectSingleNode("sourceProject");
string source = sourceNode.InnerText;
XmlNode directoryNode = node.SelectSingleNode("directory");
string directory = directoryNode.InnerText;
XmlNode updatedNode = node.SelectSingleNode("lastUpdated");
string updated = updatedNode.InnerText;
System.DateTime updatedDate;
if(System.DateTime.TryParse(updated, out updatedDate) == false)
{
updatedDate = System.DateTime.MinValue;
}
XmlNode includedProjects = node.SelectSingleNode("includedProjects");
XmlNodeList includedProjectNodes = includedProjects.SelectNodes("includedProject");
List<string> includedProjectsList = new List<string>();
foreach(XmlNode p in includedProjectNodes)
{
includedProjectsList.Add(p.InnerText);
}
XmlNode configurationNode = node.SelectSingleNode("configuration");
string configuration = configurationNode.InnerText;
XmlNode platformNode = node.SelectSingleNode("platform");
string platform = platformNode.InnerText;
// if cdb file is not there anymore, set the modified date back so that a full update will be performed
if(System.IO.File.Exists(directory + "\\" + name + ".json") == false)
{
updatedDate = System.DateTime.MinValue;
}
cdb.Name = name;
cdb.SourceProject = source;
cdb.Directory = directory;
cdb.LastUpdated = updatedDate;
cdb.IncludedProjects = includedProjectsList;
cdb.ConfigurationName = configuration;
cdb.PlatformName = platform;
return cdb;
}
private bool TryUpdateCommandObject(CommandObject co)
{
CommandObject old = _commandObjects.Find(x => x.File == co.File);
if(old != null)
{
_commandObjects.Remove(old);
_commandObjects.Add(co);
return true;
}
return false;
}
private string GetFilePath()
{
return _directory + "\\" + _name + ".json";
}
}
}
@@ -334,6 +334,12 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
string directory = item.Properties.Item("FullPath").Value.ToString();
List<string> names = new List<string>();
foreach (Property p in item.Properties)
{
names.Add(p.Name);
}
int idx = directory.LastIndexOf('\\');
if (idx != -1)
{
@@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
namespace CoatiSoftware.CoatiPlugin.Utility
{
class CompilationDatabaseList
{
private List<SolutionParser.CompilationDatabase> _cdbs = new List<SolutionParser.CompilationDatabase>();
public List<SolutionParser.CompilationDatabase> CDBs
{
get { return _cdbs; }
// set { _cdbs = value; }
}
public CompilationDatabaseList()
{
Refresh();
}
public void Append(SolutionParser.CompilationDatabase cdb)
{
if(_cdbs.Exists(item => item.Name == cdb.Name && item.Directory == cdb.Directory) == false)
{
_cdbs.Add(cdb);
}
}
public void Refresh()
{
List<SolutionParser.CompilationDatabase> cdbs = new List<SolutionParser.CompilationDatabase>();
try
{
string data = Utility.DataUtility.GetInstance().GetData();
cdbs = SolutionParser.CompilationDatabase.ParseCDBsMetaData(data);
foreach (SolutionParser.CompilationDatabase cdb in cdbs)
{
cdb.CheckCDBExists();
}
}
catch (Exception e)
{
Logging.Logging.LogError("Failed to aquire data: " + e.Message);
}
_cdbs = cdbs;
}
public List<SolutionParser.CompilationDatabase> GetCDBsForSolution(string solutionPath)
{
return _cdbs.FindAll(item => item.SourceProject == solutionPath);
}
public SolutionParser.CompilationDatabase GetCDBForSolution(string solutionPath)
{
return _cdbs.Find(item => item.SourceProject == solutionPath);
}
public SolutionParser.CompilationDatabase GetMostCurrentCDBForSolution(string solutionPath)
{
SolutionParser.CompilationDatabase result = null;
try
{
List<SolutionParser.CompilationDatabase> candidates = GetCDBsForSolution(solutionPath);
System.DateTime youngest = System.DateTime.MinValue;
foreach (SolutionParser.CompilationDatabase cdb in candidates)
{
if (cdb.LastUpdated > youngest)
{
youngest = cdb.LastUpdated;
result = cdb;
}
}
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to find cdb: " + e.Message);
}
return result;
}
public SolutionParser.CompilationDatabase GetCDBForSolution(string solutionPath, string cdbPath)
{
return _cdbs.Find(item => item.SourceProject == solutionPath && (item.Directory + "\\" + item.Name + ".json") == cdbPath);
}
public bool CheckCDBForSolutionExists(string solutionPath)
{
try
{
SolutionParser.CompilationDatabase cdb = GetCDBForSolution(solutionPath);
if (cdb != null && System.IO.File.Exists(cdb.Directory + "\\" + cdb.Name + ".json"))
{
return true;
}
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to check cdb: " + e.Message);
}
return false;
}
public void SaveMetaData()
{
try
{
XmlDocument doc = new XmlDocument();
XmlNode root = doc.CreateElement("cdbs");
foreach (SolutionParser.CompilationDatabase cdb in _cdbs)
{
XmlNode metaData = cdb.GetMetaDataXML(doc);
root.AppendChild(metaData);
}
System.IO.StringWriter writer = new System.IO.StringWriter();
XmlSerializer serializer = new XmlSerializer(typeof(XmlElement));
serializer.Serialize(writer, root);
DataUtility.GetInstance().ClearData();
DataUtility.GetInstance().AppendData(writer.ToString());
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to save meta data: " + e.Message);
}
}
public void UnloadCDBs()
{
if(_cdbs == null)
{
Logging.Logging.LogWarning("Member '_cdbs' is null, aborting.");
return;
}
foreach(SolutionParser.CompilationDatabase cdb in _cdbs)
{
cdb.ClearCommandObjects();
}
}
}
}
@@ -0,0 +1,130 @@
using System;
namespace CoatiSoftware.CoatiPlugin.Utility
{
class DataUtility
{
static private string _standardFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Coati Software\\Plugins\\VS\\";
static private string _standardFileName = "cdbs.coatidata";
static private DataUtility _instance = null;
static private bool _valid = true; // stores if a file system operation failed, indicating that there is something wrong
static public string GetStandardFolderDirectory()
{
return _standardFolder;
}
static bool Valid
{
get { return _valid; }
}
static public DataUtility GetInstance()
{
if(_instance == null)
{
_instance = new DataUtility();
}
return _instance;
}
private DataUtility()
{
CreateStandardFolderIfNotExists();
CreateStandardFileIfNotExists();
}
public void AppendData(string data)
{
try
{
using (System.IO.StreamWriter file = System.IO.File.AppendText(_standardFolder + _standardFileName))
{
file.WriteLine(data);
}
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to write data to file '" + _standardFolder + _standardFileName + "':" + e.Message);
_valid = false;
}
}
public string GetData()
{
string result = "";
try
{
string data = "";
if (System.IO.File.Exists(_standardFolder + _standardFileName))
{
using (System.IO.StreamReader file = new System.IO.StreamReader(_standardFolder + _standardFileName))
{
string line = "";
while ((line = file.ReadLine()) != null)
{
data += line;
}
}
}
result = data;
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to read data from file '" + _standardFolder + _standardFileName + "':" + e.Message);
_valid = false;
}
return result;
}
public void ClearData()
{
try
{
System.IO.File.WriteAllText(_standardFolder + _standardFileName, "");
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to clear data: " + e.Message);
}
}
private void CreateStandardFolderIfNotExists()
{
try
{
if (System.IO.Directory.Exists(_standardFolder) == false)
{
System.IO.Directory.CreateDirectory(_standardFolder);
}
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to create folder: " + e.Message);
_valid = false;
}
}
private void CreateStandardFileIfNotExists()
{
try
{
if (System.IO.File.Exists(_standardFolder + _standardFileName) == false)
{
System.IO.File.Create(_standardFolder + _standardFileName);
}
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to create file: " + e.Message);
_valid = false;
}
}
}
}
@@ -22,10 +22,15 @@ namespace CoatiSoftware.CoatiPlugin.Utility
SetActiveWindow(windowHandle);
}
}
catch(Exception e)
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
public static void OpenWindowsExplorerAtDirectory(string directory)
{
System.Diagnostics.Process.Start(directory);
}
}
}
@@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
@@ -16,34 +10,36 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
{
public class SolutionProject
{
public string m_name = "";
public bool m_include = false;
public string _name = "";
public bool _include = false;
public SolutionProject(string name, bool include)
{
m_name = name;
m_include = include;
_name = name;
_include = include;
}
}
public delegate void OnCreateProject(List<EnvDTE.Project> projects, string configurationName, string platformName, string targetDir, string fileName, string cStandard);
// public List<SolutionProject> m_projects = new List<SolutionProject>();
public Utility.SolutionUtility.SolutionStructure m_projectStructure = new Utility.SolutionUtility.SolutionStructure();
public Utility.SolutionUtility.SolutionStructure _projectStructure = new Utility.SolutionUtility.SolutionStructure();
public List<string> m_configurations = new List<string>();
public List<string> m_platforms = new List<string>();
public List<string> _configurations = new List<string>();
public List<string> _platforms = new List<string>();
public OnCreateProject m_onCreateProject = null;
public OnCreateProject _onCreateProject = null;
public string m_solutionDirectory = "";
public string m_solutionFileName = "foo";
public string _solutionDirectory = "";
public string _solutionFileName = "foo";
public bool m_containsCFiles = false;
public bool _containsCFiles = false;
private List<string> m_cStandards = new List<string>() { "c1x", "gnu1x", "iso9899:201x", "c11", "gnu11", "iso9899:2011",
private List<string> _cStandards = new List<string>() { "c1x", "gnu1x", "iso9899:201x", "c11", "gnu11", "iso9899:2011",
"c9x", "gnu9x", "iso9899:199x", "c99", "gnu99", "iso9899:1999", "iso9899:199409", "c90", "gnu90", "iso9899:1990",
"c89", "gnu89" };
public SolutionParser.CompilationDatabase _cdb = new SolutionParser.CompilationDatabase();
public ProjectSetupWindow()
{
@@ -68,47 +64,69 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
private void InitComboBoxConfigurations()
{
Logging.Logging.LogInfo("Adding " + m_configurations.Count.ToString() + " build configurations.");
Logging.Logging.LogInfo("Adding " + _configurations.Count.ToString() + " build configurations.");
foreach(string configuration in m_configurations)
foreach(string configuration in _configurations)
{
comboBoxConfiguration.Items.Add(configuration);
}
if(comboBoxConfiguration.Items.Count > 0)
{
comboBoxConfiguration.SelectedIndex = 0;
if(_cdb != null)
{
int index = comboBoxConfiguration.Items.IndexOf(_cdb.ConfigurationName);
comboBoxConfiguration.SelectedIndex = index;
}
else
{
comboBoxConfiguration.SelectedIndex = 0;
}
}
}
private void InitComboBoxPlatforms()
{
Logging.Logging.LogInfo("Adding " + m_platforms.Count.ToString() + " target platforms.");
Logging.Logging.LogInfo("Adding " + _platforms.Count.ToString() + " target platforms.");
foreach (string platform in m_platforms)
foreach (string platform in _platforms)
{
comboBoxPlatform.Items.Add(platform);
}
if(comboBoxPlatform.Items.Count > 0)
{
comboBoxPlatform.SelectedIndex = 0;
if(_cdb != null)
{
int index = comboBoxPlatform.Items.IndexOf(_cdb.PlatformName);
comboBoxPlatform.SelectedIndex = index;
}
else
{
comboBoxPlatform.SelectedIndex = 0;
}
}
}
private void InitProjectCheckList()
{
//foreach (SolutionProject project in m_projects)
//{
// treeViewProjects.Nodes.Add(new TreeNode(project.m_name));
//}
if(_cdb != null)
{
_cdb.TryLoadData();
}
foreach(Utility.SolutionUtility.SolutionStructure.Node node in m_projectStructure.Nodes)
foreach(Utility.SolutionUtility.SolutionStructure.Node node in _projectStructure.Nodes)
{
if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
{
TreeNode treeNode = new TreeNode(node.Name);
node.UserData = treeNode;
if (_cdb != null && _cdb.IncludedProjects.Exists(item => item == treeNode.Text))
{
treeNode.Checked = true;
}
treeViewProjects.Nodes.Add(treeNode);
}
else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
@@ -119,6 +137,8 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
treeViewProjects.Nodes.Add(treeNode);
}
}
UpdateCreateButtonEnabled();
}
private TreeNode[] GetSubNodes(Utility.SolutionUtility.SolutionStructure.FolderNode folderNode)
@@ -147,23 +167,30 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
private void InitTextBoxTargetDirectory()
{
Logging.Logging.LogInfo("Setting default target directory: \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(m_solutionDirectory) + "\"");
Logging.Logging.LogInfo("Setting default target directory: \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(_solutionDirectory) + "\"");
folderBrowserTargetDirectory.SelectedPath = m_solutionDirectory;
folderBrowserTargetDirectory.SelectedPath = _solutionDirectory;
string rootDirectory = folderBrowserTargetDirectory.SelectedPath.ToString();
textBoxTargetDirectory.Text = rootDirectory;
}
private void InitTextBoxFileName()
{
Logging.Logging.LogInfo("Setting default file name: '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(m_solutionFileName) + "'");
Logging.Logging.LogInfo("Setting default file name: '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(_solutionFileName) + "'");
textBoxFileName.Text = m_solutionFileName;
if(_cdb == null)
{
textBoxFileName.Text = _solutionFileName;
}
else
{
textBoxFileName.Text = _cdb.Name;
}
}
private void InitComboBoxCStandard()
{
if(m_containsCFiles == false)
if(_containsCFiles == false)
{
Logging.Logging.LogInfo("Hiding C Standard selection");
@@ -177,7 +204,7 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
comboBoxCStandard.Show();
labelCStandard.Show();
foreach(string standard in m_cStandards)
foreach(string standard in _cStandards)
{
comboBoxCStandard.Items.Add(standard);
}
@@ -202,7 +229,7 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
{
Logging.Logging.LogInfo("Create button pressed");
if (m_onCreateProject != null)
if (_onCreateProject != null)
{
string configurationName = "";
string platformName = "";
@@ -231,14 +258,14 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
}
string cStandard = "c11";
if(m_containsCFiles)
if(_containsCFiles)
{
cStandard = comboBoxCStandard.SelectedItem as string;
}
Logging.Logging.LogInfo("Setting C standard flag to " + cStandard);
m_onCreateProject(GetTreeViewProjectItems(), configurationName, platformName, targetDir, textBoxFileName.Text, cStandard);
_onCreateProject(GetTreeViewProjectItems(), configurationName, platformName, targetDir, textBoxFileName.Text, cStandard);
Close();
}
else
@@ -288,7 +315,7 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
// Stack<TreeNode> treeNodes = new Stack<TreeNode>();
Stack<Utility.SolutionUtility.SolutionStructure.Node> nodeStack = new Stack<Utility.SolutionUtility.SolutionStructure.Node>();
foreach(Utility.SolutionUtility.SolutionStructure.Node node in m_projectStructure.Nodes)
foreach(Utility.SolutionUtility.SolutionStructure.Node node in _projectStructure.Nodes)
{
nodeStack.Push(node);
}
@@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -22,60 +18,84 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
public delegate void OnFinishedCreatingCDB(CreationResult result);
private OnFinishedCreatingCDB m_onFinishedCreateCDB = null;
private OnFinishedCreatingCDB _onFinishedCreateCDB = null;
private List<EnvDTE.Project> m_projects = new List<EnvDTE.Project>();
private List<EnvDTE.Project> _projects = new List<EnvDTE.Project>();
string m_configurationName = "";
string m_platformName = "";
string m_targetDir = "";
string m_fileName = "";
string m_cStandard = "";
private string _configurationName = "";
private string _platformName = "";
private string _targetDir = "";
private string _fileName = "";
private string _cStandard = "";
private string _solutionDir = "";
CreationResult m_result = new CreationResult();
private SolutionParser.CompilationDatabase _cdb = null;
CreationResult _result = new CreationResult();
private int _threadCount = 1;
public OnFinishedCreatingCDB CallbackOnFinishedCreatingCDB
{
get { return m_onFinishedCreateCDB; }
set { m_onFinishedCreateCDB = value; }
get { return _onFinishedCreateCDB; }
set { _onFinishedCreateCDB = value; }
}
public List<EnvDTE.Project> Projects
{
get { return m_projects; }
set { m_projects = value; }
get { return _projects; }
set { _projects = value; }
}
public string ConfigurationName
{
get { return m_configurationName; }
set { m_configurationName = value; }
get { return _configurationName; }
set { _configurationName = value; }
}
public string PlatformName
{
get { return m_platformName; }
set { m_platformName = value; }
get { return _platformName; }
set { _platformName = value; }
}
public string TargetDir
{
get { return m_targetDir; }
set { m_targetDir = value; }
get { return _targetDir; }
set { _targetDir = value; }
}
public string FileName
{
get { return m_fileName; }
set { m_fileName = value; }
get { return _fileName; }
set { _fileName = value; }
}
public string CStandard
{
get { return m_cStandard; }
set { m_cStandard = value; }
get { return _cStandard; }
set { _cStandard = value; }
}
public int ThreadCount
{
get { return _threadCount; }
set { _threadCount = value; }
}
public string SolutionDir
{
get { return _solutionDir; }
set { _solutionDir = value; }
}
public SolutionParser.CompilationDatabase CDB
{
get { return _cdb; }
set { _cdb = value; }
}
public WindowCreateCDB()
{
InitializeComponent();
@@ -102,35 +122,50 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
result._cdbName = "";
result._headerDirectories = new List<string>();
SolutionParser.CompilationDatabase cdb = null;
List<string> headerDirectories = new List<string>();
Logging.Logging.LogInfo("Starting to create CDB");
SolutionParser.CompilationDatabase cdb = new SolutionParser.CompilationDatabase();
int projectsProcessed = 0;
List<string> headerDirectories = new List<string>();
SolutionParser.SolutionParser._headerDirectories.Clear();
foreach (EnvDTE.Project project in m_projects)
try
{
List<SolutionParser.CommandObject> commandObjects = SolutionParser.SolutionParser.CreateCommandObjects(project, m_configurationName, m_platformName, m_cStandard);
SolutionParser.SolutionParser._headerDirectories.Clear();
projectsProcessed++;
float relativProgress = (float)projectsProcessed/(float)m_projects.Count;
Logging.Logging.LogInfo("Processing project \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "\"");
backgroundWorker1.ReportProgress((int)(relativProgress * 100), "Processing project \"" + project.Name + "\"");
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
foreach (SolutionParser.CommandObject obj in commandObjects)
watch.Start();
cdb = CreateCommandObjects();
watch.Stop();
Logging.Logging.LogInfo("Finished, elapsed time: " + watch.ElapsedMilliseconds.ToString() + " ms");
headerDirectories = SolutionParser.SolutionParser._headerDirectories;
cdb.Name = _fileName;
cdb.Directory = _targetDir;
cdb.SourceProject = _solutionDir;
cdb.LastUpdated = DateTime.Now;
cdb.ConfigurationName = _configurationName;
cdb.PlatformName = _platformName;
cdb.IncludedProjects = new List<string>();
foreach (EnvDTE.Project p in _projects)
{
cdb.AddCommandObject(obj);
cdb.IncludedProjects.Add(p.Name);
}
cdb.Clean();
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to create CDB: " + e.Message);
}
headerDirectories = SolutionParser.SolutionParser._headerDirectories;
result._cdb = cdb;
result._cdbDirectory = m_targetDir;
result._cdbName = m_fileName;
result._cdbDirectory = _targetDir;
result._cdbName = _fileName;
result._headerDirectories = headerDirectories;
Logging.Logging.LogInfo("Done creating CDB");
@@ -138,9 +173,67 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
return result;
}
private SolutionParser.CompilationDatabase CreateCommandObjects()
{
SolutionParser.CompilationDatabase cdb = new SolutionParser.CompilationDatabase();
try
{
// parallel with tasks
Multitasking.LimitedThreadsTaskScheduler scheduler = new Multitasking.LimitedThreadsTaskScheduler(_threadCount);
TaskFactory factory = new TaskFactory(scheduler);
List<Task> tasks = new List<Task>();
Object lockObject = new Object();
int projectsProcessed = 0;
foreach (EnvDTE.Project project in _projects)
{
string projectName = project.Name;
Logging.Logging.LogInfo("Scheduling " + projectName + " for parsing.");
Task t = factory.StartNew(() =>
{
List<SolutionParser.CommandObject> commandObjects = SolutionParser.SolutionParser.CreateCommandObjects(project, _configurationName, _platformName, _cStandard);
lock(lockObject)
{
projectsProcessed++;
}
float relativProgress = (float)projectsProcessed / (float)_projects.Count;
Logging.Logging.LogInfo("Processing project \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "\"");
backgroundWorker1.ReportProgress((int)(relativProgress * 100), "Processing project \"" + project.Name + "\"");
foreach (SolutionParser.CommandObject obj in commandObjects)
{
cdb.AddOrUpdateCommandObject(obj);
}
});
tasks.Add(t);
}
int threadCount = System.Diagnostics.Process.GetCurrentProcess().Threads.Count;
Logging.Logging.LogInfo("thread count: " + threadCount.ToString());
Task.WaitAll(tasks.ToArray());
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to create CDB: " + e.Message);
}
return cdb;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
m_result = CreateCDB();
_result = CreateCDB();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
@@ -161,11 +254,11 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Cancelled == false && e.Error == null && progressBar.Value >= 100)
if(e.Cancelled == false && e.Error == null /*&& progressBar.Value >= 100*/)
{
if (m_onFinishedCreateCDB != null)
if (_onFinishedCreateCDB != null)
{
m_onFinishedCreateCDB(m_result);
_onFinishedCreateCDB(_result);
}
}
else
@@ -1,47 +1,40 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CoatiSoftware.CoatiPlugin.Wizard
{
public partial class WindowMessage : Form
{
private string m_title = "Title";
private string m_message = "Message";
private string _title = "Title";
private string _message = "Message";
public delegate void Callback();
private Callback m_onOK = null;
private Callback m_onCancel = null;
private Callback _onOK = null;
private Callback _onCancel = null;
public string Title
{
get { return m_title; }
set { m_title = value; }
get { return _title; }
set { _title = value; }
}
public string Message
{
get { return m_message; }
set { m_message = value; }
get { return _message; }
set { _message = value; }
}
public Callback OnOK
{
get { return m_onOK; }
set { m_onOK = value; }
get { return _onOK; }
set { _onOK = value; }
}
public Callback OnCancel
{
get { return m_onCancel; }
set { m_onCancel = value; }
get { return _onCancel; }
set { _onCancel = value; }
}
public WindowMessage()
@@ -51,19 +44,10 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
public void RefreshWindow()
{
Text = m_title;
labelContent.Text = m_message;
Text = _title;
labelContent.Text = _message;
//if(m_onOK != null)
//{
// buttonOK.Show();
//}
//else
//{
// buttonOK.Hide();
//}
if(m_onCancel != null)
if(_onCancel != null)
{
buttonCancel.Show();
}
@@ -75,9 +59,9 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
private void buttonCancel_Click(object sender, EventArgs e)
{
if(m_onCancel != null)
if(_onCancel != null)
{
m_onCancel();
_onCancel();
}
Close();
@@ -85,9 +69,9 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
private void buttonOK_Click(object sender, EventArgs e)
{
if(m_onOK != null)
if(_onOK != null)
{
m_onOK();
_onOK();
}
Close();
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
</packages>
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Id="acf15780-03b5-440e-a41e-db79b7043fc2" Version="0.8.31" Language="en-US" Publisher="Coati Software OG" />
<Identity Id="acf15780-03b5-440e-a41e-db79b7043fc2" Version="0.9.0" Language="en-US" Publisher="Coati Software OG" />
<DisplayName>CoatiPlugin</DisplayName>
<Description xml:space="preserve">This package allows Coati to communicate with Visual Studio and vice versa.</Description>
<MoreInfo>https://www.coati.io/</MoreInfo>
<MoreInfo>http://www.coati.io/</MoreInfo>
<ReleaseNotes>Creation of CDBs is in beta and may change in future versions</ReleaseNotes>
<Icon>coati.ico</Icon>
</Metadata>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,116 @@
param($installPath, $toolsPath, $package, $project)
# open json.net splash page on package install
# don't open if json.net is installed as a dependency
try
{
$url = "http://www.newtonsoft.com/json/install?version=" + $package.Version
$dte2 = Get-Interface $dte ([EnvDTE80.DTE2])
if ($dte2.ActiveWindow.Caption -eq "Package Manager Console")
{
# user is installing from VS NuGet console
# get reference to the window, the console host and the input history
# show webpage if "install-package newtonsoft.json" was last input
$consoleWindow = $(Get-VSComponentModel).GetService([NuGetConsole.IPowerConsoleWindow])
$props = $consoleWindow.GetType().GetProperties([System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
$prop = $props | ? { $_.Name -eq "ActiveHostInfo" } | select -first 1
if ($prop -eq $null) { return }
$hostInfo = $prop.GetValue($consoleWindow)
if ($hostInfo -eq $null) { return }
$history = $hostInfo.WpfConsole.InputHistory.History
$lastCommand = $history | select -last 1
if ($lastCommand)
{
$lastCommand = $lastCommand.Trim().ToLower()
if ($lastCommand.StartsWith("install-package") -and $lastCommand.Contains("newtonsoft.json"))
{
$dte2.ItemOperations.Navigate($url) | Out-Null
}
}
}
else
{
# user is installing from VS NuGet dialog
# get reference to the window, then smart output console provider
# show webpage if messages in buffered console contains "installing...newtonsoft.json" in last operation
$instanceField = [NuGet.Dialog.PackageManagerWindow].GetField("CurrentInstance", [System.Reflection.BindingFlags]::Static -bor `
[System.Reflection.BindingFlags]::NonPublic)
$consoleField = [NuGet.Dialog.PackageManagerWindow].GetField("_smartOutputConsoleProvider", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
if ($instanceField -eq $null -or $consoleField -eq $null) { return }
$instance = $instanceField.GetValue($null)
if ($instance -eq $null) { return }
$consoleProvider = $consoleField.GetValue($instance)
if ($consoleProvider -eq $null) { return }
$console = $consoleProvider.CreateOutputConsole($false)
$messagesField = $console.GetType().GetField("_messages", [System.Reflection.BindingFlags]::Instance -bor `
[System.Reflection.BindingFlags]::NonPublic)
if ($messagesField -eq $null) { return }
$messages = $messagesField.GetValue($console)
if ($messages -eq $null) { return }
$operations = $messages -split "=============================="
$lastOperation = $operations | select -last 1
if ($lastOperation)
{
$lastOperation = $lastOperation.ToLower()
$lines = $lastOperation -split "`r`n"
$installMatch = $lines | ? { $_.StartsWith("------- installing...newtonsoft.json ") } | select -first 1
if ($installMatch)
{
$dte2.ItemOperations.Navigate($url) | Out-Null
}
}
}
}
catch
{
try
{
$pmPane = $dte2.ToolWindows.OutputWindow.OutputWindowPanes.Item("Package Manager")
$selection = $pmPane.TextDocument.Selection
$selection.StartOfDocument($false)
$selection.EndOfDocument($true)
if ($selection.Text.StartsWith("Attempting to gather dependencies information for package 'Newtonsoft.Json." + $package.Version + "'"))
{
# don't show on upgrade
if (!$selection.Text.Contains("Removed package"))
{
$dte2.ItemOperations.Navigate($url) | Out-Null
}
}
}
catch
{
# stop potential errors from bubbling up
# worst case the splash page won't open
}
}
# still yolo
+2 -4
View File
@@ -102,6 +102,8 @@ int main(int argc, char *argv[])
{
QApplication::setApplicationName("Coati");
setupLogging();
if (QSysInfo::windowsVersion() != QSysInfo::WV_None)
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
@@ -127,8 +129,6 @@ int main(int argc, char *argv[])
setupApp(argc, argv);
setupLogging();
Application::createInstance(version, nullptr, nullptr);
ScopedFunctor f([](){
Application::destroyInstance();
@@ -179,8 +179,6 @@ int main(int argc, char *argv[])
setupApp(argc, argv);
setupLogging();
qtApp.setAttribute(Qt::AA_UseHighDpiPixmaps);
QtViewFactory viewFactory;
+1
View File
@@ -21,6 +21,7 @@
#include "settings/ApplicationSettings.h"
#include "settings/ColorScheme.h"
// useless comment
void Application::createInstance(
const Version& version, ViewFactory* viewFactory, NetworkFactory* networkFactory
){
+1
View File
@@ -1887,6 +1887,7 @@
<tr> <th scope="row">VS Port</th> <td>The port on which Visual Studio will receive messages. Note that this must match the port setting in Coati itself.</td> </tr>
<tr> <th scope="row">File Logging</th> <td>Enable log output for the plugin. Additionaly to the output file, log messages will also be displayed in VS' </td> </tr>
<tr> <th Id="vsPluginOptionObfuscation" scope="row">Log Obfuscation</th> <td>Obfuscate project- and file names as well as directories in the log output. Note that already logged data <b>will not be obfuscated retroactively</b>. A dictionary, mapping obfuscated names to original names, will be created in a seperate file.</td> </tr>
<tr> <th scope="row">Thread Count</th> <td>The number of threads used during CDB creation</td> </tr>
</tbody>
</table>
<strong>Logging</strong>