build: renaming to sourcetrail

This commit is contained in:
Andreas Stallinger
2017-04-07 13:19:09 +02:00
parent 8391a6da57
commit 045a259b2e
224 changed files with 885 additions and 4271 deletions
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourcetrailPlugin", "SourcetrailPlugin\SourcetrailPlugin.csproj", "{A585A530-E120-4C74-934E-D57ED12A7DA9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A585A530-E120-4C74-934E-D57ED12A7DA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A585A530-E120-4C74-934E-D57ED12A7DA9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A585A530-E120-4C74-934E-D57ED12A7DA9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A585A530-E120-4C74-934E-D57ED12A7DA9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,11 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project. Project-level
// suppressions either have no target or are given a specific target
// and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to "Suppress Message(s)", and click "In Project
// Suppression File". You do not need to add suppressions to this
// file manually.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1017:MarkAssembliesWithComVisible")]
@@ -0,0 +1,14 @@
// Guids.cs
// MUST match guids.h
using System;
namespace CoatiSoftware.SourcetrailPlugin
{
static class GuidList
{
public const string guidSourcetrailPluginPkgString = "acf15780-03b5-440e-a41e-db79b7043fc2";
public const string guidSourcetrailPluginCmdSetString = "0efb005b-715c-4a62-8a9b-1e5a870e6c34";
public static readonly Guid guidSourcetrailPluginCmdSet = new Guid(guidSourcetrailPluginCmdSetString);
};
}
@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
namespace CoatiSoftware.SourcetrailPlugin.Logging
{
class FileLogger : ILogger
{
private static string _directory = "";
private static string _fileNamePrefix = "Log_SourcetrailPlugin_";
private static string _fileNameSufix = ".txt";
private string _fileName = "";
private Queue<string> _messageBacklog = new Queue<string>(); // stores messages if the log file was in use at original logging time
public FileLogger()
{
DateTime time = DateTime.Now;
string dateString = "";
dateString += time.Year.ToString() + "-" + time.Month.ToString() + "-" + time.Day.ToString() + "_";
dateString += time.Hour.ToString() + "-" + time.Minute.ToString() + "-" + time.Second.ToString();
_fileName = _fileNamePrefix + dateString + _fileNameSufix;
_directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
_directory += "\\Coati Software\\Plugins\\VS\\";
if(System.IO.Directory.Exists(_directory) == false)
{
System.IO.Directory.CreateDirectory(_directory);
}
}
public void LogMessage(LogMessage message)
{
System.IO.StreamWriter writer = null;
try
{
writer = System.IO.File.AppendText(_directory + _fileName);
// write backlog to file first
while(_messageBacklog.Count > 0)
{
string bm = _messageBacklog.Dequeue();
writer.WriteLine(bm);
}
writer.WriteLine(message.ToString());
writer.Close();
}
catch(Exception e)
{
// well...file is still in use
_messageBacklog.Enqueue(message.ToString());
}
finally
{
if(writer != null)
{
writer.Close();
}
}
}
}
}
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoatiSoftware.SourcetrailPlugin.Logging
{
public interface ILogger
{
void LogMessage(LogMessage message);
}
}
@@ -0,0 +1,94 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoatiSoftware.SourcetrailPlugin.Logging
{
public class LogManager
{
private static LogManager _instance = null;
private List<ILogger> _loggers = new List<ILogger>();
private bool _loggingEnabled = false;
public List<ILogger> Loggers
{
get { return _loggers; }
set { _loggers = value; }
}
public bool LoggingEnabled
{
get { return _loggingEnabled; }
set { _loggingEnabled = value; }
}
private LogManager()
{
}
public static LogManager GetInstance()
{
if(_instance == null)
{
_instance = new LogManager();
}
return _instance;
}
public void LogInfo(string message, string sourceFile, string callingFunction, int lineNumber)
{
LogMessage logMessage = new LogMessage();
logMessage.Message = message;
logMessage.MessageType = LogMessage.LogMessageType.INFO;
logMessage.Time = DateTime.Now;
logMessage.SourceFile = sourceFile;
logMessage.CallingFunction = callingFunction;
logMessage.LineNumber = lineNumber;
Log(logMessage);
}
public void LogWarning(string message, string sourceFile, string callingFunction, int lineNumber)
{
LogMessage logMessage = new LogMessage();
logMessage.Message = message;
logMessage.MessageType = LogMessage.LogMessageType.WARNING;
logMessage.Time = DateTime.Now;
logMessage.SourceFile = sourceFile;
logMessage.CallingFunction = callingFunction;
logMessage.LineNumber = lineNumber;
Log(logMessage);
}
public void LogError(string message, string sourceFile, string callingFunction, int lineNumber)
{
LogMessage logMessage = new LogMessage();
logMessage.Message = message;
logMessage.MessageType = LogMessage.LogMessageType.ERROR;
logMessage.Time = DateTime.Now;
logMessage.SourceFile = sourceFile;
logMessage.CallingFunction = callingFunction;
logMessage.LineNumber = lineNumber;
Log(logMessage);
}
private void Log(LogMessage message)
{
if(_loggingEnabled == true)
{
foreach (ILogger logger in _loggers)
{
logger.LogMessage(message);
}
}
}
}
}
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoatiSoftware.SourcetrailPlugin.Logging
{
public class LogMessage
{
public enum LogMessageType
{
UNKNOWN = 0,
INFO,
WARNING,
ERROR
}
private string _message = "";
private DateTime _time = new DateTime();
private LogMessageType _messageType = LogMessageType.UNKNOWN;
private string _sourceFile = "";
private string _callingFunction = "";
private int _lineNumber = -1;
public string Message
{
get { return _message; }
set { _message = value; }
}
public DateTime Time
{
get { return _time; }
set { _time = value; }
}
public LogMessageType MessageType
{
get { return _messageType; }
set { _messageType = value; }
}
public string SourceFile
{
get { return _sourceFile; }
set { _sourceFile = value; }
}
public string CallingFunction
{
get { return _callingFunction; }
set { _callingFunction = value; }
}
public int LineNumber
{
get { return _lineNumber; }
set { _lineNumber = value; }
}
public override string ToString()
{
string result = "";
result += _time.Hour.ToString() + ":" + _time.Minute.ToString() + ":"+ _time.Second.ToString();
result += "\t";
result += _messageType.ToString();
result += "\t";
result += _sourceFile + ":" + _lineNumber.ToString();
result += " (";
result += _callingFunction;
result += ")";
result += "\t\t";
result += _message;
return result;
}
}
}
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
namespace CoatiSoftware.SourcetrailPlugin.Logging
{
public class Logging
{
public static void LogInfo(string message, [CallerFilePath] string file = "", [CallerMemberName] string member = "", [CallerLineNumber] int line = 0)
{
int idx = file.LastIndexOf('\\');
if(idx > -1)
{
file = file.Substring(idx + 1);
}
LogManager.GetInstance().LogInfo(message, file, member, line);
}
public static void LogWarning(string message, [CallerFilePath] string file = "", [CallerMemberName] string member = "", [CallerLineNumber] int line = 0)
{
int idx = file.LastIndexOf('\\');
if (idx > -1)
{
file = file.Substring(idx + 1);
}
LogManager.GetInstance().LogWarning(message, file, member, line);
}
public static void LogError(string message, [CallerFilePath] string file = "", [CallerMemberName] string member = "", [CallerLineNumber] int line = 0)
{
int idx = file.LastIndexOf('\\');
if (idx > -1)
{
file = file.Substring(idx + 1);
}
LogManager.GetInstance().LogError(message, file, member, line);
}
}
}
@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
namespace CoatiSoftware.SourcetrailPlugin.Logging.Obfuscation
{
class NameObfuscator
{
private static NameObfuscator _instance = null;
private Dictionary<string, string> _dictionary = new Dictionary<string, string>();
private bool _enabled = false;
char _currentChar = 'a';
int _currentInt = 0;
private static string _directory = "";
private static string _fileNamePrefix = "Dictionary_SourcetrailPlugin_";
private static string _fileNameSufix = ".txt";
private string _fileName = "";
private Queue<string> _messageBacklog = new Queue<string>(); // stores messages if the log file was in use at original logging time
private NameObfuscator()
{
DateTime time = DateTime.Now;
string dateString = "";
dateString += time.Year.ToString() + "-" + time.Month.ToString() + "-" + time.Day.ToString() + "_";
dateString += time.Hour.ToString() + "-" + time.Minute.ToString() + "-" + time.Second.ToString();
_fileName = _fileNamePrefix + dateString + _fileNameSufix;
_directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
_directory += "\\Coati Software\\Plugins\\VS\\";
if (System.IO.Directory.Exists(_directory) == false)
{
System.IO.Directory.CreateDirectory(_directory);
}
}
private static void CreateInstance()
{
if (_instance == null)
{
_instance = new NameObfuscator();
}
}
public static string GetObfuscatedName(string originalName)
{
CreateInstance();
if (_instance._enabled)
{
if (_instance._dictionary.ContainsKey(originalName))
{
return _instance._dictionary[originalName];
}
else
{
string newName = _instance.GetNewName();
_instance._dictionary[originalName] = newName;
_instance.WriteDictionaryEntryToFile(newName, originalName); // key and value reversed because that's the way the dictionary file is to be used...
return newName;
}
}
else
{
return originalName;
}
}
public static void Enabled(bool enabled)
{
CreateInstance();
_instance._enabled = enabled;
}
private string GetNewName()
{
string name = "";
name = _currentChar.ToString() + _currentInt.ToString();
++_currentChar;
if((int)_currentChar > 122)
{
_currentChar = 'a';
++_currentInt;
}
return name;
}
private void WriteDictionaryEntryToFile(string key, string value)
{
System.IO.StreamWriter writer = null;
string message = key + " - " + value;
try
{
writer = System.IO.File.AppendText(_directory + _fileName);
// write backlog to file first
while (_messageBacklog.Count > 0)
{
string bm = _messageBacklog.Dequeue();
writer.WriteLine(bm);
}
writer.WriteLine(message.ToString());
writer.Close();
}
catch (Exception e)
{
// well...file is still in use
_messageBacklog.Enqueue(message.ToString());
}
finally
{
if (writer != null)
{
writer.Close();
}
}
}
}
}
@@ -0,0 +1,80 @@
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.Diagnostics;
namespace CoatiSoftware.SourcetrailPlugin.Logging
{
class VSOutputLogger : ILogger
{
private EnvDTE.DTE _dte = null;
private OutputWindowPane _pane = null;
public VSOutputLogger(EnvDTE.DTE dte)
{
_dte = dte;
}
public void LogMessage(LogMessage message)
{
if (message.MessageType == SourcetrailPlugin.Logging.LogMessage.LogMessageType.INFO)
{
Debug.WriteLine(message.Message, "Info");
WriteToOutputWindow("Info: " + message.Message);
}
if (message.MessageType == SourcetrailPlugin.Logging.LogMessage.LogMessageType.WARNING)
{
Debug.WriteLine(message.Message, "Warning");
WriteToOutputWindow("Warning: " + message.Message);
}
if (message.MessageType == SourcetrailPlugin.Logging.LogMessage.LogMessageType.ERROR)
{
Debug.WriteLine(message.Message, "Error");
WriteToOutputWindow("Error: " + message.Message);
}
}
private void WriteToOutputWindow(string message)
{
string paneName = "Sourcetrail Log";
if (_dte.Windows.Count > 0)
{
Window window = _dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
OutputWindow outputWindow = (OutputWindow)window.Object;
OutputWindowPanes panes = outputWindow.OutputWindowPanes;
if(_pane == null)
{
try
{
for (int i = 0; i < panes.Count; i++)
{
OutputWindowPane pane = panes.Item(i);
if (pane.Name.Equals(paneName, StringComparison.CurrentCultureIgnoreCase))
{
_pane = outputWindow.OutputWindowPanes.Item(i);
break;
}
}
}
catch (Exception e)
{
}
}
if (_pane == null)
{
_pane = outputWindow.OutputWindowPanes.Add(paneName);
}
_pane.OutputString(message + '\n');
}
}
}
}
@@ -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.SourcetrailPlugin.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);
}
}
}
}
@@ -0,0 +1,15 @@
// PkgCmdID.cs
// MUST match PkgCmdID.h
using System;
namespace CoatiSoftware.SourcetrailPlugin
{
static class PkgCmdIDList
{
public const uint cmdidSourcetrailSetActiveToken = 0x104;
public const uint cmdidSourcetrailCreateProject = 0x105;
public const uint cmdidSourcetrailCreateCDB = 0x106;
public const uint cmdidSourcetrailOpenLogFolder = 0x107;
};
}
@@ -0,0 +1,36 @@
using System;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SourcetrailPlugin")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Coati Software")]
[assembly: AssemblyProduct("SourcetrailPlugin")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: CLSCompliant(false)]
[assembly: NeutralResourcesLanguage("en-US")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CoatiSoftware.SourcetrailPlugin {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CoatiSoftware.SourcetrailPlugin.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}
@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
VS SDK Notes: This resx file contains the resources that will be consumed directly by your package.
For example, if you chose to create a tool window, there is a resource with ID 'CanNotCreateWindow'. This
is used in VsPkg.cs to determine the string to show the user if there is an error when attempting to create
the tool window.
Resources that are accessed directly from your package *by Visual Studio* are stored in the VSPackage.resx
file.
-->
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

@@ -0,0 +1,53 @@
namespace CoatiSoftware.SourcetrailPlugin.SolutionParser
{
public class CommandObject
{
private string _file = "";
private string _directory = "";
private string _command = "";
public string File
{
get { return _file; }
set
{
_file = value;
//_file = _file.Replace('"', '\'');
//_file = _file.Replace('\"', '\'');
//_file = _file.Replace("\\\"", "'");
}
}
public string Directory
{
get { return _directory; }
set { _directory = value; }
}
public string Command
{
get { return _command; }
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}";
return result;
}
}
}
@@ -0,0 +1,351 @@
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Xml;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Threading;
using System;
namespace CoatiSoftware.SourcetrailPlugin.SolutionParser
{
public class CompilationDatabase
{
private List<CommandObject> _commandObjects = new List<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
{
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 int CommandObjectCount
{
get { return _commandObjects.Count; }
}
public void AddOrUpdateCommandObject(CommandObject commandObject, bool saveImmediatly = false)
{
_commandObjects.Add(commandObject); // updating is not efficient as it is
}
// 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()
{
string result = "[\n";
foreach(CommandObject cm in _commandObjects)
{
result += cm.SerializeJSON() + ",";
}
result += "\n]";
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";
}
}
}
@@ -0,0 +1,691 @@
using System;
using System.Collections.Generic;
using System.Linq;
using EnvDTE;
using Microsoft.VisualStudio.VCProjectEngine;
using System.Collections;
using System.IO;
using System.Diagnostics;
namespace CoatiSoftware.SourcetrailPlugin.SolutionParser
{
class SolutionParser
{
static private List<Guid> _reloadedProjectGuids = new List<Guid>();
static private List<string> _compatibilityFlags = new List<string>() { "-fms-extensions", "-fms-compatibility" };
static private string _compatibilityVersionFlagBase = "-fms-compatibility-version="; // I want to get the exact version at runtime for this flag, therefore I keep it seperate from the others to make things a bit easier...
static private string _compatibilityVersionFlag = _compatibilityVersionFlagBase + "19"; // This default version would correspond to VS2015
static public List<string> _additionalCompileFlags = new List<string>();
static public List<string> _headerDirectories = new List<string>();
static private List<string> _extensionWhiteList = new List<string>() { "c", "cc", "cpp", "cxx", "C", "h", "hpp" };
public static List<CommandObject> CreateCommandObjects(Project project, string configurationName, string platformName, string cStandard)
{
Logging.Logging.LogInfo("Creating command objects from project " + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name));
List<CommandObject> result = new List<CommandObject>();
DTE dte = project.DTE;
Guid projectGuid = Utility.ProjectUtility.ReloadProject(project);
VCProject vcProject = project.Object as VCProject;
if (vcProject == null)
{
Logging.Logging.LogWarning("Project '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "' could not be converted to VCProject, skipping.");
return result;
}
SetCompatibilityVersionFlag(vcProject, configurationName, platformName);
// gather include paths and preprocessor definitions of the project
List<string> includeDirectories = new List<string>();
List<string> preprocessorDefinitions = new List<string>();
Tuple<List<string>, List<string>> pathsAndFlags = GetProjectIncludeDirectoriesAndPreprocessorDefs(vcProject, configurationName, platformName);
includeDirectories = pathsAndFlags.Item1;
preprocessorDefinitions = pathsAndFlags.Item2;
// create command objects for all applicable project items
List<ProjectItem> projectItems = Utility.ProjectUtility.GetProjectItems(project);
VCConfiguration vcProjectConfig = GetProjectConfiguration(vcProject, configurationName, platformName);
string cppStandard = GetCppStandardString(vcProjectConfig);
Logging.Logging.LogInfo("Found C++ standard " + cppStandard + ".");
foreach (EnvDTE.ProjectItem item in projectItems)
{
CommandObject cmdObj = CreateCommandObject(item, includeDirectories, preprocessorDefinitions, cppStandard, cStandard, configurationName, platformName);
if (cmdObj != null)
{
result.Add(cmdObj);
}
}
if (projectGuid != Guid.Empty)
{
Utility.ProjectUtility.UnloadProject(projectGuid, dte);
}
_headerDirectories = _headerDirectories.Distinct().ToList();
return result;
}
static private Tuple<List<string>, List<string>> GetProjectIncludeDirectoriesAndPreprocessorDefs(VCProject project, string configurationName, string platformName)
{
Logging.Logging.LogInfo("Attempting to retreive Include Directories and Preprocessor Definitions for project '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "'");
List<string> includeDirectories = new List<string>();
List<string> preprocessorDefinitions = new List<string>();
VCConfiguration vcProjectConfig = null;
try
{
vcProjectConfig = GetProjectConfiguration(project, configurationName, platformName);
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to retreive project configuration: " + e.Message);
}
if (vcProjectConfig != null)
{
try
{
// get additional include directories
// source: http://www.mztools.com/articles/2014/MZ2014005.aspx
IEnumerable projectTools = vcProjectConfig.Tools as IEnumerable;
foreach (Object tool in projectTools)
{
VCCLCompilerTool compilerTool = tool as VCCLCompilerTool;
if (compilerTool != null)
{
string additionalIncludeDirs = compilerTool.FullIncludePath;
string preprocessorDefinition = compilerTool.PreprocessorDefinitions;
string[] prepDefs = preprocessorDefinition.Split(';');
foreach (string prepDef in prepDefs)
{
preprocessorDefinitions.Add(prepDef);
}
string[] directories = additionalIncludeDirs.Split(';');
foreach (string directory in directories)
{
if (directory.Length <= 0)
{
continue;
}
string dir = directory;
// In case of a project-relative path
if (directory.Length > 0 && directory.Substring(0, 1) == ".")
{
dir = project.ProjectDirectory + directory;
}
// make it canonical
dir = new Uri(dir).LocalPath;
includeDirectories.Add(dir);
}
break; // TODO: find some documentation on why the break is needed
// Apparently only the first 'tool' is needed, but why?
}
}
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to retreive include directories: " + e.Message);
return new Tuple<List<string>, List<string>>(new List<string>(), new List<string>());
}
try
{
VCPlatform platform = vcProjectConfig.Platform as VCPlatform;
string platformIncludeDirectories = platform.IncludeDirectories;
string[] seperatedDirectories = platformIncludeDirectories.Split(';');
foreach (string directory in seperatedDirectories)
{
string resolvedDirectory = ResolveVSMacro(vcProjectConfig, directory);
string[] splitResolvedDirectory = resolvedDirectory.Split(';'); // resolved macros might result in concatenated paths
foreach (string p in splitResolvedDirectory)
{
includeDirectories.Add(p);
}
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
return new Tuple<List<string>, List<string>>(new List<string>(), new List<string>());
}
}
else
{
Logging.Logging.LogWarning("Could not retreive Project Configuration. No include directories or preprocessor definitions could be retreived.");
return new Tuple<List<string>, List<string>>(new List<string>(), new List<string>());
}
includeDirectories = includeDirectories.Distinct().ToList();
preprocessorDefinitions = preprocessorDefinitions.Distinct().ToList();
Logging.Logging.LogInfo("Found " + includeDirectories.Count.ToString() + " distinct include directories and " + preprocessorDefinitions.Count.ToString() + " distinct preprocessor definitions.");
Logging.Logging.LogInfo("Attempting to resolve and clean up.");
for (int i = 0; i < includeDirectories.Count; i++)
{
string path = includeDirectories.ElementAt(i).Replace("\\", "/"); // backslashes would cause some string-escaping hassles...
bool exists = true;
if (System.IO.Directory.Exists(path) == false)
{
exists = false;
}
// could be a relative path...
if (exists == false)
{
if (System.IO.Directory.Exists(project.ProjectDirectory + path) == false)
{
exists = false;
}
else
{
path = project.ProjectDirectory + path;
path = path.Replace("\\", "/");
exists = true;
}
}
if (exists == false)
{
includeDirectories.RemoveAt(i);
i--;
}
else
{
includeDirectories[i] = path;
}
}
Logging.Logging.LogInfo("Found " + includeDirectories.Count.ToString() + " include directories and " + preprocessorDefinitions.Count.ToString() + " preprocessor definitions");
return new Tuple<List<string>, List<string>>(includeDirectories, preprocessorDefinitions);
}
static private VCConfiguration GetProjectConfiguration(VCProject project, string configurationName, string platformName)
{
Logging.Logging.LogInfo("Attempting to retreive project configuration");
if (project == null)
{
return null;
}
IEnumerable configurations = project.Configurations as IEnumerable;
foreach (Object configuration in configurations)
{
VCConfiguration vcProjectConfig = configuration as VCConfiguration;
if (vcProjectConfig != null &&
vcProjectConfig.ConfigurationName == configurationName &&
vcProjectConfig.Platform.Name == platformName)
{
return vcProjectConfig;
}
}
Logging.Logging.LogError("Failed to find project config matching with \"" + configurationName + "\"");
return null;
}
static private CommandObject CreateCommandObject(EnvDTE.ProjectItem item, List<string> includeDirectories, List<string> preprocessorDefinitions, string vcStandard, string cStandard, string configurationName, string platformName)
{
string objectName = item.Name;
Logging.Logging.LogInfo("Starting to create Command Object from item '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(item.Name) + "'");
try
{
DTE dte = item.DTE;
if (dte == null)
{
Logging.Logging.LogError("Failed to retreive DTE object. Abort creating command object.");
}
VCFile vcFile = item.Object as VCFile;
string subType = vcFile.SubType;
VCProject project = vcFile.project;
VCConfiguration vcConfig = GetProjectConfiguration(project, configurationName, platformName);
if (vcConfig == null)
{
Logging.Logging.LogError("Project Configuration is null.");
return null;
}
VCFileConfiguration fc = vcFile.GetFileConfigurationForProjectConfiguration(vcConfig);
VCCLCompilerTool t = fc.Tool as VCCLCompilerTool;
if (t == null)
{
Logging.Logging.LogInfo("Unable to retrieve build tool. Using extension white list to determine file type.");
}
if (IsSourceFile(item, t))
{
CommandObject commandObject = new CommandObject();
commandObject.File = item.Name;
// only write source files to cdb, headers are implicit
// however, retreive header directory
if (CheckIsHeader(item))
{
Properties props = item.Properties;
foreach (Property prop in props)
{
string propName = prop.Name;
string propValue = prop.Value as String;
if (propName == "FullPath")
{
int i = propValue.LastIndexOf('\\');
propValue = propValue.Substring(0, i);
_headerDirectories.Add(propValue);
}
}
return null;
}
string additionalOptions = "";
if (t != null)
{
additionalOptions = t.AdditionalOptions;
CompileAsOptions compileAs = t.CompileAs; // VCCLCompilerToolShim
if (additionalOptions == "$(NOINHERIT)")
{
additionalOptions = "";
}
// check wheter it's a .c file, we don't want that...
// TODO: there is a property for comilation as .c or .cpp file (/TC and /TP), try to retrieve it
string extension = item.Properties.Item("Extension").Value.ToString();
if (compileAs == CompileAsOptions.compileAsC)
{
vcStandard = "-std=" + cStandard;
}
}
// if a language standard was defined in the additional options the 'vcStandard' string is not used
if (additionalOptions.Contains("-std="))
{
vcStandard = "";
}
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)
{
directory = directory.Substring(0, idx + 1);
}
directory = directory.Replace('\\', '/');
commandObject.File = directory + item.Name;
commandObject.Directory = System.IO.Path.GetDirectoryName(dte.Solution.FullName); // TODO: replace with actual cdb location
commandObject.Directory = commandObject.Directory.Replace('\\', '/');
commandObject.Command = "clang-tool ";
foreach (string flag in _compatibilityFlags)
{
commandObject.Command += flag + " ";
}
commandObject.Command += _compatibilityVersionFlag + " ";
foreach (string dir in includeDirectories)
{
commandObject.Command += " -isystem '" + dir + "' "; // using '-isystem' because it allows for use of quotes and pointy brackets in source files. In other words it's more robust. It's slower than '-I' though
}
foreach (string prepDef in preprocessorDefinitions)
{
commandObject.Command += " -D " + prepDef + " ";
}
foreach (string flag in _additionalCompileFlags)
{
commandObject.Command += " -D " + flag + " ";
}
commandObject.Command += vcStandard + " ";
commandObject.Command += additionalOptions + " ";
commandObject.Command += "'" + commandObject.File + "'";
return commandObject;
}
else
{
Logging.Logging.LogInfo("Item discarded, wrong code model");
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
Logging.Logging.LogError("Failed to create command object.");
return null;
}
static private bool IsSourceFile(ProjectItem item, VCCLCompilerTool tool)
{
if (tool != null) // if the tool is null it's probably not a normal VC project, indicating that the file code model is unavailable
{
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
{
return true;
}
}
else if (_extensionWhiteList.Contains(GetFileExtension(item)))
{
return true;
}
return false;
}
static private bool CheckIsHeader(EnvDTE.ProjectItem item)
{
Properties props = item.Properties;
string propString = "";
try
{
foreach (Property prop in props)
{
string propName = prop.Name;
string propValue = prop.Value as String;
propString += propName + " - " + propValue + "; ";
if (propName == "ItemType")
{
if (propValue as String == "ClInclude")
{
return true;
}
}
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
return false;
}
static private string ResolveVSMacro(VCConfiguration vcProjectConfig, string path)
{
string result = path;
try
{
Tuple<int, int> potentialMacroPosition = Utility.StringUtility.FindFirstRange(path, "$(", ")");
if (potentialMacroPosition != null)
{
string potentialMacro = path.Substring(potentialMacroPosition.Item1, potentialMacroPosition.Item2 - potentialMacroPosition.Item1 + 1);
string resolvedMacro = vcProjectConfig.Evaluate(potentialMacro);
result = path.Substring(0, potentialMacroPosition.Item1) + resolvedMacro + path.Substring(potentialMacroPosition.Item2 + 1);
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
return result;
}
static private void ReloadAll(DTE dte)
{
if (dte == null)
{
return;
}
EnvDTE.Solution solution = dte.Solution;
List<EnvDTE.Project> projects = Utility.SolutionUtility.GetSolutionProjectList(dte);
foreach (EnvDTE.Project project in projects)
{
_reloadedProjectGuids.Add(Utility.ProjectUtility.ReloadProject(project));
}
}
static private void UnloadReloadedProjects(DTE dte)
{
foreach (Guid guid in _reloadedProjectGuids)
{
Utility.ProjectUtility.UnloadProject(guid, dte);
}
}
static private void SetCompatibilityVersionFlag(VCProject project, string configurationName, string platformName)
{
Logging.Logging.LogInfo("Determining CL.exe (C++ compiler) version");
VCConfiguration vcProjectConfig = GetProjectConfiguration(project, configurationName, platformName);
if (vcProjectConfig != null)
{
IEnumerable projectTools = vcProjectConfig.Tools as IEnumerable;
foreach (Object tool in projectTools)
{
try
{
VCCLCompilerTool compilerTool = tool as VCCLCompilerTool;
if (compilerTool != null)
{
int majorCompilerVersion = GetCLMajorVersion(compilerTool, vcProjectConfig);
if (majorCompilerVersion > -1)
{
Logging.Logging.LogInfo("Found compiler version " + majorCompilerVersion.ToString());
_compatibilityVersionFlag = _compatibilityVersionFlagBase + majorCompilerVersion.ToString();
return;
}
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
}
else
{
Logging.Logging.LogWarning("Failed to retreive VC Project Configuration. Using default compiler version");
}
}
static private int GetCLMajorVersion(VCCLCompilerTool compilerTool, VCConfiguration vcProjectConfig)
{
Logging.Logging.LogInfo("Looking up CL.exe (C++ compiler)");
if (compilerTool == null || vcProjectConfig == null)
{
return -1;
}
try
{
VCPlatform platform = vcProjectConfig.Platform as VCPlatform;
string executableDirectories = platform.ExecutableDirectories;
string[] seperatedDirectories = executableDirectories.Split(';');
List<string> finalDirectories = new List<string>();
foreach (string directory in seperatedDirectories)
{
string resolvedDirectory = ResolveVSMacro(vcProjectConfig, directory);
string[] splitResolvedDirectory = resolvedDirectory.Split(';'); // resolved macros might result in concatenated paths
foreach (string d in splitResolvedDirectory)
{
finalDirectories.Add(d);
}
}
string toolPath = compilerTool.ToolPath;
Logging.Logging.LogInfo("Found " + finalDirectories.Count.ToString() + " possible compiler directories.");
foreach (string fd in finalDirectories)
{
string path = fd + "\\" + toolPath;
if (File.Exists(path))
{
FileVersionInfo info = FileVersionInfo.GetVersionInfo(path);
int version = info.FileMajorPart;
Logging.Logging.LogInfo("Found compiler location. Compiler tool version is " + version.ToString());
return version;
}
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
Logging.Logging.LogWarning("Failed to find C++ compiler tool.");
return -1;
}
// AFAIK there is no way to programmatically get the c++ standard version supported by any given VS version
// instead I'm refearing to the VS docu for that information
// https://msdn.microsoft.com/en-us/library/hh567368.aspx
static private string GetCppStandardString(VCConfiguration vcProjectConfig)
{
if (vcProjectConfig == null)
{
return "";
}
string result = "";
IVCRulePropertyStorage rules = null;
try
{
rules = vcProjectConfig.Rules.Item("ConfigurationGeneral");
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
return "";
}
if (rules != null)
{
try
{
string toolset = rules.GetUnevaluatedPropertyValue("PlatformToolset");
string justNumbers = new String(toolset.Where(Char.IsDigit).ToArray());
int versionNumber = int.Parse(justNumbers);
if (versionNumber < 120) // version 11 (2012)
{
result = "-std=c++11";
}
else if (versionNumber < 130) // version 12 (2013)
{
result = "-std=c++14";
}
else if (versionNumber < 150) // version 14 (2015)
{
result = "-std=c++14";
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
return result;
}
static private string GetFileExtension(ProjectItem item)
{
if (item == null)
{
return "";
}
string name = item.Name;
int idx = name.LastIndexOf(".");
if (idx > -1 && idx < name.Length - 1)
{
return name.Substring(idx + 1);
}
else
{
return "";
}
}
}
}
@@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>4.0</OldToolsVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A585A530-E120-4C74-934E-D57ED12A7DA9}</ProjectGuid>
<ProjectTypeGuids>{82b43b9b-a64c-4715-b499-d71e9ca2bd60};{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CoatiSoftware.SourcetrailPlugin</RootNamespace>
<AssemblyName>sourcetrail_plugin_vs</AssemblyName>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<RunCodeAnalysis>true</RunCodeAnalysis>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.VisualStudio.OLE.Interop" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.8.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.9.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.10.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Interop.11.0">
<EmbedInteropTypes>true</EmbedInteropTypes>
</Reference>
<Reference Include="Microsoft.VisualStudio.TemplateWizardInterface, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.TextManager.Interop" />
<Reference Include="Microsoft.VisualStudio.Shell.11.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.11.0" />
<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" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Design" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<COMReference Include="EnvDTE">
<Guid>{80CC9F66-E7D8-4DDD-85B6-D9E6CD0E93E2}</Guid>
<VersionMajor>8</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="EnvDTE100">
<Guid>{26AD1324-4B7C-44BC-84F8-B86AED45729F}</Guid>
<VersionMajor>10</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="EnvDTE80">
<Guid>{1A31287A-4D7D-413E-8E32-3B374931BD89}</Guid>
<VersionMajor>8</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="EnvDTE90">
<Guid>{2CE2370E-D744-4936-A090-3FFFE667B0E1}</Guid>
<VersionMajor>9</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="Microsoft.VisualStudio.CommandBars">
<Guid>{1CBA492E-7263-47BB-87FE-639000619B15}</Guid>
<VersionMajor>8</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
<COMReference Include="stdole">
<Guid>{00020430-0000-0000-C000-000000000046}</Guid>
<VersionMajor>2</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>primary</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>False</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Logging\FileLogger.cs" />
<Compile Include="Logging\ILogger.cs" />
<Compile Include="Logging\Logging.cs" />
<Compile Include="Logging\LogManager.cs" />
<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" />
<Compile Include="Utility\NetworkUtility.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="SourcetrailPluginPackage.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PkgCmdID.cs" />
<Compile Include="SolutionParser\CommandObject.cs" />
<Compile Include="SolutionParser\CompilationDatabase.cs" />
<Compile Include="SolutionParser\SolutionParser.cs" />
<Compile Include="Utility\ProjectUtility.cs" />
<Compile Include="Utility\QueuedFileWriter.cs" />
<Compile Include="Utility\SolutionUtility.cs" />
<Compile Include="Utility\SystemUtility.cs" />
<Compile Include="Utility\StringUtility.cs" />
<Compile Include="Wizard\WindowCDBReady.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Wizard\WindowCDBReady.Designer.cs">
<DependentUpon>WindowCDBReady.cs</DependentUpon>
</Compile>
<Compile Include="Wizard\WindowCreateCDB.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Wizard\WindowCreateCDB.Designer.cs">
<DependentUpon>WindowCreateCDB.cs</DependentUpon>
</Compile>
<Compile Include="Wizard\ProjectSetupWindow.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Wizard\ProjectSetupWindow.Designer.cs">
<DependentUpon>ProjectSetupWindow.cs</DependentUpon>
</Compile>
<Compile Include="Wizard\WindowMessage.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Wizard\WindowMessage.Designer.cs">
<DependentUpon>WindowMessage.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="VSPackage.resx">
<MergeWithCTO>true</MergeWithCTO>
<ManifestResourceName>VSPackage</ManifestResourceName>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Wizard\WindowCDBReady.resx">
<DependentUpon>WindowCDBReady.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizard\WindowCreateCDB.resx">
<DependentUpon>WindowCreateCDB.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizard\ProjectSetupWindow.resx">
<DependentUpon>ProjectSetupWindow.cs</DependentUpon>
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ProjectSetupWindow1.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Wizard\WindowMessage.resx">
<DependentUpon>WindowMessage.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<None Include="Key.snk" />
</ItemGroup>
<ItemGroup>
<VSCTCompile Include="SourcetrailPlugin.vsct">
<ResourceName>Menus.ctmenu</ResourceName>
<SubType>Designer</SubType>
</VSCTCompile>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\favicon_16x16.png" />
</ItemGroup>
<ItemGroup>
<Content Include="sourcetrail.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<IncludeInVSIX>true</IncludeInVSIX>
</Content>
</ItemGroup>
<ItemGroup />
<PropertyGroup>
<UseCodebase>true</UseCodebase>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\VSSDK\Microsoft.VsSDK.targets" Condition="'$(VSToolsPath)' != ''" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<StartAction>Program</StartAction>
<StartProgram>C:\Program Files %28x86%29\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe</StartProgram>
<StartArguments>/rootsuffix Exp</StartArguments>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<StartAction>Program</StartAction>
<StartProgram>C:\Program Files %28x86%29\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe</StartProgram>
<StartArguments>/rootsuffix Exp</StartArguments>
</PropertyGroup>
</Project>
@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This is the file that defines the actual layout and type of the commands.
It is divided in different sections (e.g. command definition, command
placement, ...), with each defining a specific set of properties.
See the comment before each section for more details about how to
use it. -->
<!-- The VSCT compiler (the tool that translates this file into the binary
format that VisualStudio will consume) has the ability to run a preprocessor
on the vsct file; this preprocessor is (usually) the C++ preprocessor, so
it is possible to define includes and macros with the same syntax used
in C++ files. Using this ability of the compiler here, we include some files
defining some of the constants that we will use inside the file. -->
<!--This is the file that defines the IDs for all the commands exposed by VisualStudio. -->
<Extern href="stdidcmd.h"/>
<!--This header contains the command ids for the menus provided by the shell. -->
<Extern href="vsshlids.h"/>
<!--The Commands section is where we the commands, menus and menu groups are defined.
This section uses a Guid to identify the package that provides the command defined inside it. -->
<Commands package="guidSourcetrailPluginPkg">
<Bitmaps>
<Bitmap guid="icon" href="Resources\favicon_16x16.png" usedList="icon0"/>
</Bitmaps>
<Groups>
<Group guid="guidSourcetrailPluginCmdSet" id="ContextMenuGroup" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_CODEWIN"/>
</Group>
<Group guid="guidSourcetrailPluginCmdSet" id="TopLevelMenu" priority="0x0600">
<Parent guid="guidSHLMainMenu" id="IDM_VS_TOOL_MAINMENU"/>
</Group>
<Group guid="guidSourcetrailPluginCmdSet" id="SubMenu" priority="0x0600">
<Parent guid="guidSourcetrailPluginCmdSet" id="TopLevelMenu"/>
</Group>
<!--
<Group guid="guidSourcetrailPluginCmdSet" id="HelpMenu" priority="0x0600">
<Parent guid="guidSourcetrailPluginCmdSet" id="TopLevelMenu"/>
</Group>
-->
</Groups>
<Buttons>
<Button guid="guidSourcetrailPluginCmdSet" id="cmdidSourcetrailSetActiveToken" priority="0x0100" type="Button">
<Parent guid="guidSourcetrailPluginCmdSet" id="ContextMenuGroup" />
<Icon guid="icon" id="icon0" />
<Strings>
<ButtonText>Set active Token</ButtonText>
</Strings>
</Button>
<Button guid="guidSourcetrailPluginCmdSet" id="cmdidSourcetrailCreateCDB" priority="0x0100" type="Button">
<Parent guid="guidSourcetrailPluginCmdSet" id="SubMenu" />
<Icon guid="icon" id="icon0" />
<Strings>
<ButtonText>Create CDB</ButtonText>
</Strings>
</Button>
<Button guid="guidSourcetrailPluginCmdSet" id="cmdidSourcetrailOpenLogFolder" priority="0x0100" type="Button">
<Parent guid="guidSourcetrailPluginCmdSet" id="SubMenu" />
<Strings>
<ButtonText>Open Log Directory</ButtonText>
</Strings>
</Button>
<!--
<Button guid="guidSourcetrailPluginCmdSet" id="cmdidSourcetrailHelp" priority="0x0100" type="Button">
<Parent guid="guidSourcetrailPluginCmdSet" id="HelpMenu" />
<Strings>
<ButtonText>Online Help</ButtonText>
</Strings>
</Button>
-->
</Buttons>
<Menus>
<Menu guid="guidSourcetrailPluginCmdSet" id="TopLevelMenu" priority="0x700" type="Menu">
<Parent guid="guidSHLMainMenu" id="IDG_VS_MM_TOOLSADDINS"/>
<Strings>
<ButtonText>Sourcetrail</ButtonText>
<CommandName>Sourcetrail</CommandName>
</Strings>
</Menu>
<!--
<Menu guid="guidSourcetrailPluginCmdSet" id="HelpMenu" priority="0x700" type="Menu">
<Parent guid="guidSourcetrailPluginCmdSet" id="TopLevelMenu"/>
<Strings>
<ButtonText>Sourcetrail Help</ButtonText>
<CommandName>Sourcetrail Help</CommandName>
</Strings>
</Menu>
-->
</Menus>
</Commands>
<Symbols>
<!-- This is the package guid. -->
<GuidSymbol name="guidSourcetrailPluginPkg" value="{acf15780-03b5-440e-a41e-db79b7043fc2}" />
<!-- This is the guid used to group the menu commands together -->
<GuidSymbol name="guidSourcetrailPluginCmdSet" value="{0efb005b-715c-4a62-8a9b-1e5a870e6c34}">
<IDSymbol name="ContextMenuGroup" value="0x1020" />
<IDSymbol name="cmdidSourcetrailPing" value="0x0100" />
<IDSymbol name="cmdidSourcetrailFile" value="0x0101"/>
<IDSymbol name="cmdidSourcetrailGetActiveFileName" value="0x0102"/>
<IDSymbol name="cmdidSourcetrailGetActiveLineNumber" value="0x0103"/>
<IDSymbol name="cmdidSourcetrailSetActiveToken" value="0x0104"/>
<IDSymbol name="cmdidSourcetrailCreateProject" value="0x0105"/>
<IDSymbol name="cmdidSourcetrailCreateCDB" value="0x0106"/>
<IDSymbol name="cmdidSourcetrailOpenLogFolder" value="0x0107"/>
<IDSymbol name="TopLevelMenu" value="0x1021"/>
<IDSymbol name="SubMenu" value="0x1022"/>
<IDSymbol name="HelpMenu" value="0x1023"/>
<IDSymbol name="cmdidSourcetrailHelp" value="0x1024"/>
</GuidSymbol>
<GuidSymbol name="guidImages" value="{e447cfde-511d-4f75-80c1-a40b8a03152a}" >
<IDSymbol name="bmpPic1" value="1" />
<IDSymbol name="bmpPic2" value="2" />
<IDSymbol name="bmpPicSearch" value="3" />
<IDSymbol name="bmpPicX" value="4" />
<IDSymbol name="bmpPicArrows" value="5" />
<IDSymbol name="bmpPicStrikethrough" value="6" />
</GuidSymbol>
<GuidSymbol name="icon" value="{403BFDD2-B84C-4BCE-A1D1-B16F9F2B8230}" >
<IDSymbol name="icon0" value="1" />
</GuidSymbol>
</Symbols>
</CommandTable>
@@ -0,0 +1,590 @@
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.ComponentModel.Design;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell;
using System.Collections.Generic;
using System.IO;
using EnvDTE;
using System.Windows.Forms;
namespace CoatiSoftware.SourcetrailPlugin
{
public class OptionPageGrid : DialogPage
{
private uint _serverPort = 6666;
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("Sourcetrail")]
[DisplayName("VS Port")]
[Description("The port on which Visual Studio will receive messages")]
public uint ServerPort
{
get { return _serverPort; }
set
{
_serverPort = value;
if (_serverPortChangeCallback != null)
{
_serverPortChangeCallback();
}
}
}
[Category("Sourcetrail")]
[DisplayName("Sourcetrail Port")]
[Description("The port on which Sourcetrail will receive messages")]
public uint ClientPort
{
get { return _clientPort; }
set
{
_clientPort = value;
if (_clientPortChangeCallback != null)
{
_clientPortChangeCallback();
}
}
}
[Category("Sourcetrail")]
[DisplayName("File Logging")]
[Description("Enables or disables file logging for the plugin")]
public bool LoggingEnabled
{
get { return _logging; }
set
{
_logging = value;
if(_loggingToggled != null)
{
_loggingToggled();
}
}
}
[Category("Sourcetrail")]
[DisplayName("Log Obfuscation")]
[Description("Names will be obfuscated in log files. Note that already logged data will not be obfuscated retroactively. A dictionary file will be created that you can use to make sense of obfuscated logs. Keep this dictionary to yourself!")]
public bool ObfuscateLogging
{
get { return _obfuscateLogging; }
set
{
_obfuscateLogging = value;
if (_obfuscationToggled != null)
{
_obfuscationToggled();
}
}
}
[Category("Sourcetrail")]
[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()
{
}
}
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid(GuidList.guidSourcetrailPluginPkgString)]
[ProvideAutoLoad(Microsoft.VisualStudio.Shell.Interop.UIContextGuids80.NoSolution)]
[ProvideOptionPage(typeof(OptionPageGrid), "Sourcetrail", "Sourcetrail Settings", 0, 0, true)]
public sealed class SourcetrailPluginPackage : Package
{
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
{
OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
return page.ServerPort;
}
}
public uint ClientPort
{
get
{
OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
return page.ClientPort;
}
}
public bool LoggingEnabled
{
get
{
OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
return page.LoggingEnabled;
}
}
public bool LogObfuscationEnabled
{
get
{
OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
return page.ObfuscateLogging;
}
}
public uint ThreadCount
{
get
{
OptionPageGrid page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
return page.ThreadCount;
}
}
System.Threading.Thread _serverThread = null;
public SourcetrailPluginPackage()
{}
protected override void Initialize()
{
base.Initialize();
InitLogging();
InitNetwork();
Utility.FileUtility._errorCallback = new Utility.FileUtility.ErrorCallback(OnFileUtilityError);
// register callbacks for changes of plugin settings
OptionPageGrid._serverPortChangeCallback = new OptionPageGrid.Callback(OnServerPortChanged);
OptionPageGrid._clientPortChangeCallback = new OptionPageGrid.Callback(OnClientPortChanged);
OptionPageGrid._loggingToggled = new OptionPageGrid.Callback(OnLoggingToggled);
OptionPageGrid._obfuscationToggled = new OptionPageGrid.Callback(OnObfuscationToggled);
// register the plugin UI elements
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
if ( null != mcs )
{
CommandID setActiveTokenCommandID = new CommandID(GuidList.guidSourcetrailPluginCmdSet, (int)PkgCmdIDList.cmdidSourcetrailSetActiveToken);
CommandID createProjectID = new CommandID(GuidList.guidSourcetrailPluginCmdSet, (int)PkgCmdIDList.cmdidSourcetrailCreateProject);
CommandID createCDBID = new CommandID(GuidList.guidSourcetrailPluginCmdSet, (int)PkgCmdIDList.cmdidSourcetrailCreateCDB);
CommandID openLogDirID = new CommandID(GuidList.guidSourcetrailPluginCmdSet, (int)PkgCmdIDList.cmdidSourcetrailOpenLogFolder);
_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
DTE dte = (DTE)GetService(typeof(DTE));
_solutionEvents = dte.Events.SolutionEvents;
_solutionEvents.Opened += OnSolutionOpened;
_solutionEvents.AfterClosing += OnSolutionClosed;
SendPing();
Logging.Logging.LogInfo("Initialization done");
}
void OnSolutionOpened()
{
Logging.Logging.LogInfo("A solution was loaded, checking languages");
try
{
// the sourcetrail ui should only be enabled when the solution contains C/C++ projects
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)
{
if (language == CodeModelLanguageConstants.vsCMLanguageVC
|| language == CodeModelLanguageConstants.vsCMLanguageMC)
{
Logging.Logging.LogInfo("C/C++ project was detected");
enable = true;
}
}
if (enable)
{
Logging.Logging.LogInfo("Enabling plugin UI");
_menuItemSetActiveToken.Enabled = true;
_menuItemCreateProject.Enabled = true;
_menuItemCreateCDB.Enabled = true;
_validSolutionLoaded = true;
}
else
{
_validSolutionLoaded = false;
Logging.Logging.LogInfo("No C/C++ project was detected");
}
}
catch(Exception e)
{
DisplayMessage("Error", e.Message);
Logging.Logging.LogError(e.Message);
}
}
void OnSolutionClosed()
{
Logging.Logging.LogInfo("Solution closed, disabling plugin UI");
_menuItemSetActiveToken.Enabled = false;
_menuItemCreateProject.Enabled = false;
_menuItemCreateCDB.Enabled = false;
_validSolutionLoaded = false;
}
private void InitNetwork()
{
Logging.Logging.LogInfo("Initializing Network with Server Port " + ServerPort.ToString() + " and Client Port " + ClientPort.ToString());
Utility.AsynchronousSocketListener._port = ServerPort;
Utility.AsynchronousSocketListener server = new Utility.AsynchronousSocketListener();
Utility.AsynchronousSocketListener._onReadCallback = new Utility.AsynchronousSocketListener.OnReadCallback(OnNetworkReadCallback);
Utility.AsynchronousSocketListener._onErrorCallback = new Utility.AsynchronousSocketListener.OnReadCallback(OnNetworkErrorCallback);
_serverThread = new System.Threading.Thread(server.DoWork);
_serverThread.Start();
Utility.AsynchronousClient._port = ClientPort;
Utility.AsynchronousClient._onErrorCallback = new Utility.AsynchronousSocketListener.OnReadCallback(OnNetworkErrorCallback);
}
private void InitLogging()
{
DTE dte = (DTE)GetService(typeof(DTE));
Logging.FileLogger fileLogger = new Logging.FileLogger();
Logging.VSOutputLogger vsLogger = new Logging.VSOutputLogger(dte);
Logging.LogManager.GetInstance().Loggers.Add(fileLogger);
Logging.LogManager.GetInstance().Loggers.Add(vsLogger);
Logging.LogManager.GetInstance().LoggingEnabled = LoggingEnabled;
Logging.Obfuscation.NameObfuscator.Enabled(LogObfuscationEnabled);
Logging.Logging.LogInfo("Logging initialized");
}
private void SendPing()
{
string message = Utility.NetworkProtocolUtility.CreatePingMessage();
Utility.AsynchronousClient.Send(message);
}
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;
createCDB.PlatformName = platformName;
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;
createCDB.StartWorking();
createCDB.ShowDialog();
}
private void HandleFinishedCDB(Wizard.WindowCreateCDB.CreationResult creationResult)
{
if(creationResult._cdb != null && creationResult._cdbDirectory.Length > 0 && creationResult._cdbName.Length > 0)
{
_cdbList.AppendOrUpdate(creationResult._cdb);
_cdbList.SaveMetaData();
Wizard.WindowCDBReady dialog = new Wizard.WindowCDBReady();
dialog.setData(creationResult);
dialog.ShowDialog();
_cdbList.Refresh();
}
else
{
Logging.Logging.LogError("Invalid data received");
}
}
private void MenuItemCallback(object sender, EventArgs e)
{
MenuCommand menuCommand = sender as MenuCommand;
DTE dte = (DTE)GetService(typeof(DTE));
if (menuCommand != null)
{
if (menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidSourcetrailSetActiveToken)
{
string fileName = Utility.FileUtility.GetActiveDocumentName(dte);
string filePath = Utility.FileUtility.GetActiveDocumentPath(dte);
int lineNumber = Utility.FileUtility.GetActiveLineNumber(dte);
int columnNumber = Utility.FileUtility.GetActiveColumnNumber(dte);
string message = Utility.NetworkProtocolUtility.CreateActivateTokenMessage(filePath + fileName, lineNumber, columnNumber);
Utility.AsynchronousClient.Send(message);
}
else if(menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidSourcetrailCreateCDB)
{
CreateCompilationDatabase(dte);
}
else if(menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidSourcetrailCreateProject)
{
// show hint to use CDB methad (only for CDB beta) and create project on ok
Wizard.WindowMessage windowMessage = new Wizard.WindowMessage();
windowMessage.Title = "Hint";
windowMessage.Message = "Consider using 'Create CDB' if errors arise during Sourcetrail's indexing. This will become standard in the future.";
windowMessage.OnOK = CreateSourcetrailProjectOld;
windowMessage.RefreshWindow();
windowMessage.ShowDialog();
}
else if(menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidSourcetrailOpenLogFolder)
{
Utility.SystemUtility.OpenWindowsExplorerAtDirectory(Utility.DataUtility.GetStandardFolderDirectory());
}
}
}
// will be removed once the CDB project creation is fully integrated
private void CreateSourcetrailProjectOld()
{
DTE dte = (DTE)GetService(typeof(DTE));
string solutionName = Utility.SolutionUtility.GetSolutionPath(dte);
if (solutionName == "") // TODO: make a better fallback for non-existant solution
{
List<string> items = Utility.SolutionUtility.GetSolutionProjectsFullNames(dte);
if (items.Count > 0)
{
solutionName = items[0];
}
}
if (solutionName.Length > 0)
{
string message = Utility.NetworkProtocolUtility.CreateCreateProjectMessage(solutionName);
Utility.AsynchronousClient.Send(message);
}
else
{
DisplayMessage("Sourcetrail", "Can not create a Sourcetrail Project. Please check whether your VS solution is a valid C or C++ solution and is saved.");
}
}
private void OnNetworkReadCallback(string message)
{
Utility.NetworkProtocolUtility.MESSAGE_TYPE messageType = Utility.NetworkProtocolUtility.GetMessageType(message);
if(messageType == Utility.NetworkProtocolUtility.MESSAGE_TYPE.MOVE_CURSOR)
{
Utility.NetworkProtocolUtility.CursorPosition cursorPosition = Utility.NetworkProtocolUtility.ParseSetCursorMessage(message);
if (cursorPosition.Valid)
{
cursorPosition.ColumnNumber += 1; // VS counts columns starting at 1, sourcetrail starts at 0
DTE dte = (DTE)GetService(typeof(DTE));
if (Utility.FileUtility.OpenSourceFile(dte, cursorPosition.FilePath))
{
Utility.FileUtility.GoToLine(dte, cursorPosition.LineNumber, cursorPosition.ColumnNumber);
Utility.SystemUtility.GetWindowFocus();
}
}
}
else if(messageType == Utility.NetworkProtocolUtility.MESSAGE_TYPE.CREATE_CDB)
{
if(_validSolutionLoaded)
{
DTE dte = (DTE)GetService(typeof(DTE));
CreateCompilationDatabase(dte);
}
}
else if(messageType == Utility.NetworkProtocolUtility.MESSAGE_TYPE.PING)
{
SendPing();
}
}
private void OnNetworkErrorCallback(string message)
{
Logging.Logging.LogError("Network Error: " + message.ToString());
DisplayMessage("Sourcetrail Network Error", message);
}
private void OnFileUtilityError(string message)
{
Logging.Logging.LogError("File Error: " + message.ToString());
DisplayMessage("Sourcetrail File Error", message);
}
private void OnServerPortChanged()
{
Logging.Logging.LogInfo("Changing Server Port to " + ServerPort.ToString());
Utility.AsynchronousSocketListener._port = ServerPort;
_serverThread.Abort();
Utility.AsynchronousSocketListener server = new Utility.AsynchronousSocketListener();
_serverThread = new System.Threading.Thread(server.DoWork);
_serverThread.Start();
}
private void OnClientPortChanged()
{
Logging.Logging.LogInfo("Changing Client Port to " + ClientPort.ToString());
Utility.AsynchronousClient._port = ClientPort;
}
private void OnLoggingToggled()
{
Logging.LogManager.GetInstance().LoggingEnabled = LoggingEnabled;
if(LoggingEnabled)
{
Logging.Logging.LogInfo("Logging enabled");
}
}
private void OnObfuscationToggled()
{
Logging.Obfuscation.NameObfuscator.Enabled(LogObfuscationEnabled);
if(LogObfuscationEnabled)
{
Logging.Logging.LogInfo("Log Obfuscation enabled");
}
else
{
Logging.Logging.LogInfo("Log Obfuscation disabled");
}
}
private void DisplayMessage(string title, string message)
{
IVsUIShell uiShell = (IVsUIShell)GetService(typeof(SVsUIShell));
Guid clsid = Guid.Empty;
int result;
Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(uiShell.ShowMessageBox(
0,
ref clsid,
title,
message,
string.Empty,
0,
OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
OLEMSGICON.OLEMSGICON_INFO,
0, // false
out result));
}
private void CreateCompilationDatabase(DTE dte)
{
Logging.Logging.LogInfo("Preparing CDB dialog");
Wizard.ProjectSetupWindow window = new Wizard.ProjectSetupWindow();
Utility.SolutionUtility.SolutionStructure projectStructure = Utility.SolutionUtility.GetSolutionVCProjects(dte);
List<List<string>> configsAndPlatforms = Utility.SolutionUtility.GetConfigurationAndPlatformNames(dte);
window._projectStructure = projectStructure;
window._configurations = configsAndPlatforms[0];
window._platforms = configsAndPlatforms[1];
string directory = System.IO.Path.GetDirectoryName(dte.Solution.FullName);
window._solutionDirectory = directory;
string solutionName = System.IO.Path.GetFileNameWithoutExtension(dte.Solution.FullName);
window._solutionFileName = solutionName;
bool containsCFiles = true; // Utility.SolutionUtility.ContainsCFiles(dte); // takes ridiculously long, I'd rather just display the option by default
window._containsCFiles = containsCFiles;
window._cdb = _cdbList.GetMostCurrentCDBForSolution(Utility.SolutionUtility.GetSolutionPath(dte));
window.UpdateGUI();
window._onCreateProject = OnCreateProject;
window.ShowDialog();
}
}
}
@@ -0,0 +1,159 @@
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
namespace CoatiSoftware.SourcetrailPlugin.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 AppendOrUpdate(SolutionParser.CompilationDatabase cdb)
{
if(_cdbs.Exists(item => item.Name == cdb.Name && item.Directory == cdb.Directory) == false)
{
_cdbs.Add(cdb);
}
else
{
int idx = _cdbs.FindIndex(item => item.Name == cdb.Name && item.Directory == cdb.Directory);
_cdbs[idx] = 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.SourcetrailPlugin.Utility
{
class DataUtility
{
static private string _standardFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Coati Software\\Plugins\\VS\\";
static private string _standardFileName = "cdbs.sourcetraildata";
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;
}
}
}
}
@@ -0,0 +1,78 @@
using System;
using EnvDTE;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
class FileUtility
{
public delegate void ErrorCallback(string message);
public static ErrorCallback _errorCallback = null;
/**
* Returns true when file was found, false otherwise
*/
public static bool OpenSourceFile(DTE dte, string fileName)
{
try
{
dte.ItemOperations.OpenFile(fileName);
return true;
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
if (_errorCallback != null)
{
_errorCallback("Failed to open file at " + fileName);
}
string message = "Failed to open file at " + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName);
Logging.Logging.LogError(message);
return false;
}
}
public static void GoToLine(DTE dte, int lineNumber, int columnNumber)
{
try
{
((EnvDTE.TextSelection)dte.ActiveDocument.Selection).MoveToLineAndOffset(lineNumber, columnNumber);
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
if (_errorCallback != null)
{
_errorCallback("Failed to set cursor to position [" + lineNumber.ToString() + "," + columnNumber.ToString() + "]");
string message = "Failed to set cursor to position [" + lineNumber.ToString() + "," + columnNumber.ToString() + "]";
Logging.Logging.LogError(message);
}
}
}
public static string GetActiveDocumentName(DTE dte)
{
return dte.ActiveDocument.Name;
}
public static string GetActiveDocumentPath(DTE dte)
{
return dte.ActiveDocument.Path;
}
public static int GetActiveLineNumber(DTE dte)
{
return ((EnvDTE.TextSelection)dte.ActiveDocument.Selection).ActivePoint.Line;
}
public static int GetActiveColumnNumber(DTE dte)
{
return ((EnvDTE.TextSelection)dte.ActiveDocument.Selection).ActivePoint.LineCharOffset;
}
}
}
@@ -0,0 +1,301 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
class NetworkProtocolUtility
{
private static string s_divider = ">>";
private static string s_setActiveTokenPrefix = "setActiveToken";
private static string s_moveCursorPrefix = "moveCursor";
private static string s_endOfMessageToken = "<EOM>";
private static string s_createProjectPrefix = "createProject"; // deprecate
private static string s_createCDBProjectPrefix = "createCDBProject";
private static string s_ideId = "vs";
private static string s_createCDBPrefix = "createCDB";
private static string s_pingPrefix = "ping";
public enum MESSAGE_TYPE
{
UNKNOWN = 0,
MOVE_CURSOR,
CREATE_CDB,
PING
}
public class CursorPosition
{
private string _filePath = "";
private int _lineNumber = 0;
private int _columnNumber = 0;
private bool _valid = false;
public string FilePath
{
get { return _filePath; }
set { _filePath = value; }
}
public int LineNumber
{
get { return _lineNumber; }
set { _lineNumber = value; }
}
public int ColumnNumber
{
get { return _columnNumber; }
set { _columnNumber = value; }
}
public bool Valid
{
get { return _valid; }
set { _valid = value; }
}
}
public class Ping
{
private string _id = "";
private bool _valid = false;
public string Id
{
get { return _id; }
set { _id = value; }
}
public bool Valid
{
get { return _valid; }
set { _valid = value; }
}
}
public static string CreateActivateTokenMessage(string filePath, int lineNumber, int columnNumber)
{
string message = s_setActiveTokenPrefix;
message += s_divider;
message += filePath;
message += s_divider;
message += lineNumber.ToString();
message += s_divider;
message += columnNumber.ToString();
message += s_endOfMessageToken;
return message;
}
public static string CreateCreateProjectMessage(string solutionPath)
{
string message = s_createProjectPrefix;
message += s_divider;
message += solutionPath;
message += s_divider;
message += s_ideId;
message += s_endOfMessageToken;
return message;
}
public static string CreateCreateProjectMessage(string cdbPath, List<string> headerPaths)
{
string message = s_createCDBProjectPrefix;
message += s_divider;
message += cdbPath;
message += s_divider;
foreach(string path in headerPaths)
{
message += path;
message += s_divider;
}
message += s_ideId;
message += s_endOfMessageToken;
return message;
}
public static string CreatePingMessage()
{
string message = s_pingPrefix;
message += s_divider;
message += s_ideId;
message += s_endOfMessageToken;
return message;
}
public static MESSAGE_TYPE GetMessageType(string message)
{
List<string> tokens = GetMessageTokens(message);
if (tokens.Count > 0)
{
if (tokens[0] == s_createCDBPrefix)
{
return MESSAGE_TYPE.CREATE_CDB;
}
else if (tokens[0] == s_moveCursorPrefix)
{
return MESSAGE_TYPE.MOVE_CURSOR;
}
else if (tokens[0] == s_pingPrefix)
{
return MESSAGE_TYPE.PING;
}
else
{
return MESSAGE_TYPE.UNKNOWN;
}
}
return MESSAGE_TYPE.UNKNOWN;
}
public static CursorPosition ParseSetCursorMessage(string message)
{
CursorPosition result = new CursorPosition();
List<string> tokens = GetMessageTokens(message);
if(tokens.Count != 4)
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Invalid token count for 'move cursor' message. Expected 4, but got " + tokens.Count.ToString());
return result;
}
if(tokens[0] != s_moveCursorPrefix)
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Invalid message type. Expected '" + s_moveCursorPrefix + "' but got '" + tokens[0] + "'");
return result;
}
result.FilePath = tokens[1];
int lineNumber = 0;
if(int.TryParse(tokens[2], out lineNumber))
{
result.LineNumber = lineNumber;
}
else
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Failed to parse line number");
return result;
}
int columnNumber = 0;
if(int.TryParse(tokens[3], out columnNumber))
{
result.ColumnNumber = columnNumber;
}
else
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Failed to parse column number");
return result;
}
result.Valid = true;
return result;
}
public static Ping ParsePingMessage(string message)
{
Ping result = new Ping();
List<string> tokens = GetMessageTokens(message);
if(tokens.Count != 2)
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Invalid token count for 'ping' message. Expected 2, but got " + tokens.Count.ToString());
return result;
}
if (tokens[0] != s_pingPrefix)
{
Logging.Logging.LogError("Invalid message: " + message);
Logging.Logging.LogError("Invalid message type. Expected '" + s_pingPrefix + "' but got '" + tokens[0] + "'");
return result;
}
result.Id = tokens[1];
result.Valid = true;
return result;
}
private static List<string> GetMessageTokens(string message)
{
List<string> tokens = new List<string>();
if(RemoveEOMString(ref message))
{
tokens = message.Split(s_divider.ToCharArray()).ToList();
// removing empty strings
List<string> cleanTokens = new List<string>();
foreach(string token in tokens)
{
if(token.Length > 0)
{
cleanTokens.Add(token);
}
}
tokens = cleanTokens;
}
else
{
Logging.Logging.LogError("");
}
return tokens;
}
// returns false if no EOM string was found
private static bool RemoveEOMString(ref string message)
{
if (message.IndexOf(s_endOfMessageToken) > -1)
{
message = message.Substring(0, message.IndexOf(s_endOfMessageToken));
return true;
}
return false;
}
}
}
@@ -0,0 +1,277 @@
using System;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
public class StateObject
{
public Socket _workSocket = null;
public const int _bufferSize = 1024;
public byte[] _buffer = new byte[_bufferSize];
public StringBuilder _stringBuilder = new StringBuilder();
}
public class AsynchronousSocketListener
{
public static ManualResetEvent _allDone = new ManualResetEvent(false);
public delegate void OnReadCallback(string message);
public static OnReadCallback _onReadCallback = null;
public static OnReadCallback _onErrorCallback = null;
private static string _endOfMessageToken = "<EOM>";
public static uint _port = 6666;
public AsynchronousSocketListener()
{
}
public void DoWork()
{
StartListening();
}
public static void StartListening()
{
const string ipAddressString = "127.0.0.1";
byte[] bytes = new Byte[1024];
IPAddress ipAddress = IPAddress.Parse(ipAddressString);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, (int)_port);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
_allDone.WaitOne();
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
public static void AcceptCallback(IAsyncResult ar)
{
try
{
_allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject state = new StateObject();
state._workSocket = handler;
handler.BeginReceive(state._buffer, 0, StateObject._bufferSize, 0, new AsyncCallback(ReadCallback), state);
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
public static void ReadCallback(IAsyncResult ar)
{
try
{
string content = String.Empty;
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state._workSocket;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
state._stringBuilder.Append(Encoding.ASCII.GetString(state._buffer, 0, bytesRead));
content = state._stringBuilder.ToString();
if (content.IndexOf(_endOfMessageToken) > -1)
{
if (_onReadCallback != null)
{
_onReadCallback(content);
}
}
else
{
handler.BeginReceive(state._buffer, 0, StateObject._bufferSize, 0, new AsyncCallback(ReadCallback), state);
}
}
}
catch(Exception e)
{
Logging.Logging.LogError("Excpetion: " + e.Message);
}
}
private static void Send(Socket handler, String data)
{
try
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
}
catch(Exception e)
{
Logging.Logging.LogError("Excpetion: " + e.Message);
}
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
Logging.Logging.LogInfo("Sent " + bytesSent.ToString() + " bytes to client.");
}
catch (Exception e)
{
Logging.Logging.LogError("Excpetion: " + e.Message);
if (_onErrorCallback != null)
{
_onErrorCallback(e.ToString());
}
}
}
}
public class AsynchronousClient
{
public static uint _port = 6667;
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static String response = String.Empty;
public static AsynchronousSocketListener.OnReadCallback _onErrorCallback = null;
public static void Send(string message)
{
IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
IPEndPoint remoteEP = new IPEndPoint(ipAddress, (int)_port);
Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
IAsyncResult ar = client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
if (!connectDone.WaitOne(2000))
{
client.EndConnect(ar);
client.Shutdown(SocketShutdown.Both);
client.Close();
Logging.Logging.LogWarning("Connection timed out, message was not sent");
return;
}
Send(client, message);
sendDone.WaitOne();
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
finally
{
if(client.Connected)
{
client.Shutdown(SocketShutdown.Both);
client.Close();
}
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
if (client.Connected == false)
{
return;
}
client.EndConnect(ar);
connectDone.Set();
}
catch (Exception e)
{
Logging.Logging.LogError("Excpetion: " + e.Message);
if (_onErrorCallback != null)
{
_onErrorCallback(e.ToString());
}
}
}
private static void Send(Socket client, String data)
{
try
{
byte[] byteData = Encoding.ASCII.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
sendDone.Set();
}
catch (Exception e)
{
Logging.Logging.LogError("Excpetion: " + e.Message);
if (_onErrorCallback != null)
{
if (e is ObjectDisposedException)
{
// get this exception every once in a while
// doesn't seem to do much, no idea yet why it's there to begin with
}
else
{
_onErrorCallback(e.ToString());
}
}
}
}
}
}
@@ -0,0 +1,166 @@
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.Collections;
using System.Collections.Generic;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
public class ProjectUtility
{
public static bool ContainsCFiles(Project project)
{
List<ProjectItem> projectItems = GetProjectItems(project);
try
{
foreach (EnvDTE.ProjectItem item in projectItems)
{
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
{
string extension = item.Properties.Item("Extension").Value.ToString();
if (extension == ".c")
{
return true;
}
}
}
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
return false;
}
static public List<ProjectItem> GetProjectItems(Project project)
{
List<ProjectItem> items = new List<ProjectItem>();
IEnumerator itemEnumerator = project.ProjectItems.GetEnumerator();
while (itemEnumerator.MoveNext())
{
ProjectItem currentItem = (ProjectItem)itemEnumerator.Current;
items.Add(GetProjectSubItemsRecursive(currentItem, ref items));
}
return items;
}
static private ProjectItem GetProjectSubItemsRecursive(ProjectItem item, ref List<ProjectItem> projectItems)
{
if (item.ProjectItems == null)
{
return item;
}
IEnumerator items = item.ProjectItems.GetEnumerator();
while (items.MoveNext())
{
ProjectItem currentItem = (ProjectItem)items.Current;
projectItems.Add(GetProjectSubItemsRecursive(currentItem, ref projectItems));
}
return item;
}
// returns true if the project was reloaded, false if the project did not need to be reloaded
static public Guid ReloadProject(Project project)
{
Logging.Logging.LogInfo("Attempting to reload project");
try
{
if (project != null && project.Kind == EnvDTE.Constants.vsProjectKindUnmodeled)
{
DTE dte = project.DTE;
ServiceProvider sp = new ServiceProvider(dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
IVsSolution vsSolution = sp.GetService(typeof(SVsSolution)) as IVsSolution;
IVsHierarchy hierarchy;
string solutionDirectory = "";
string solutionFile = "";
string userOptions = "";
vsSolution.GetSolutionInfo(out solutionDirectory, out solutionFile, out userOptions);
vsSolution.GetProjectOfUniqueName(solutionDirectory + project.UniqueName, out hierarchy);
if (hierarchy != null)
{
Guid projectGuid;
hierarchy.GetGuidProperty(
VSConstants.VSITEMID_ROOT,
(int)__VSHPROPID.VSHPROPID_ProjectIDGuid,
out projectGuid);
if (projectGuid != null)
{
Logging.Logging.LogInfo("Project '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "' with GUID {" + projectGuid.ToString() + "} loaded.");
(vsSolution as IVsSolution4).ReloadProject(projectGuid);
return projectGuid;
}
else
{
Logging.Logging.LogError("Failed to load project '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "'");
}
}
else
{
Logging.Logging.LogError("Failed to retreive IVsHierarchy. Can't load project '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "'");
}
}
else
{
if (project == null)
{
Logging.Logging.LogWarning("Project is null");
}
else
{
Logging.Logging.LogInfo("Project '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "' is already loaded");
}
}
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
return Guid.Empty;
}
return Guid.Empty;
}
static public void UnloadProject(Guid guid, DTE dte)
{
Logging.Logging.LogInfo("Attempting to unload project with GUID {" + guid.ToString() + "}");
if (dte == null)
{
return;
}
try
{
ServiceProvider sp = new ServiceProvider(dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
IVsSolution vsSolution = sp.GetService(typeof(SVsSolution)) as IVsSolution;
(vsSolution as IVsSolution4).UnloadProject(guid, (uint)_VSProjectUnloadStatus.UNLOADSTATUS_UnloadedByUser);
Logging.Logging.LogInfo("Done unloading project with GUID {" + guid.ToString() + "}");
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
}
}
@@ -0,0 +1,158 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
class QueuedFileWriter
{
private bool _working = false;
Thread _workerThread = null;
private static ReaderWriterLockSlim _statusLock = new ReaderWriterLockSlim();
private static ReaderWriterLockSlim _queueLock = new ReaderWriterLockSlim();
private static ReaderWriterLockSlim _fileLock = new ReaderWriterLockSlim();
private Queue<string> _inputQueue = new Queue<string>();
private Queue<string> _outputQueue = new Queue<string>();
private string _targetDirectory = "";
private string _fileName = "";
private int _messagesReceived = 0;
private int _messageWrittenCount = 0;
public string TargetDirectory
{
get { return _targetDirectory; }
set { _targetDirectory = value; }
}
public string FileName
{
get { return _fileName; }
set { _fileName = value; }
}
public void pushMessage(string message)
{
_queueLock.EnterWriteLock();
_messagesReceived++;
try
{
_inputQueue.Enqueue(message);
}
catch(Exception e)
{
Logging.Logging.LogError(e.Message);
}
finally
{
_queueLock.ExitWriteLock();
}
}
public void startWorking()
{
_statusLock.EnterReadLock();
if (_working == true)
{
return;
}
_statusLock.ExitReadLock();
_statusLock.EnterWriteLock();
_working = true;
_workerThread = new Thread(new ThreadStart(work));
_workerThread.Start();
_statusLock.ExitWriteLock();
}
public void stopWorking()
{
_statusLock.EnterWriteLock();
_working = false;
_statusLock.ExitWriteLock();
if(_workerThread != null)
{
_workerThread.Join();
}
// write remaining messages if stop was called
_queueLock.EnterWriteLock();
try
{
writeQueueToFile(ref _inputQueue);
writeQueueToFile(ref _outputQueue);
Logging.Logging.LogInfo("final commit done");
}
catch(Exception e)
{
Logging.Logging.LogError(e.Message);
}
finally
{
_queueLock.ExitWriteLock();
}
Logging.Logging.LogInfo("Messages received: " + _messagesReceived);
Logging.Logging.LogInfo("Messages written: " + _messageWrittenCount);
}
private void work()
{
bool working = true;
while(working)
{
commit();
_statusLock.EnterReadLock();
working = _working;
_statusLock.ExitReadLock();
}
}
private void commit()
{
_queueLock.EnterWriteLock();
Queue<string> tmpQueue = _inputQueue;
_inputQueue = _outputQueue;
_outputQueue = tmpQueue;
_queueLock.ExitWriteLock();
writeQueueToFile(ref _outputQueue);
}
private void writeQueueToFile(ref Queue<string> messageQueue)
{
_fileLock.EnterWriteLock();
try
{
while(messageQueue.Count > 0)
{
_messageWrittenCount++;
string message = messageQueue.Dequeue();
File.AppendAllText(_targetDirectory + "\\" + _fileName, message);
}
}
catch (Exception e)
{
Logging.Logging.LogError(e.Message);
}
finally
{
_fileLock.ExitWriteLock();
}
}
}
}
@@ -0,0 +1,422 @@
using System;
using System.Collections.Generic;
using System.Linq;
using EnvDTE;
using EnvDTE80;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
public class SolutionUtility
{
[DllImport("ole32.dll")]
private static extern void CreateBindCtx(int reserved, out IBindCtx bindCtx);
[DllImport("ole32.dll")]
private static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable runningObjectTable);
public class SolutionStructure
{
public class Node
{
public enum NodeType
{
UNKNOWN = 0,
PROJECT,
FOLDER
};
public string Name = "";
public Project Project = null;
public Object UserData = null;
public virtual NodeType GetNodeType() { throw (new NotImplementedException()); }
}
public class FolderNode : Node
{
public List<Node> SubNodes = new List<Node>();
public override NodeType GetNodeType() { return NodeType.FOLDER; }
}
public class ProjectNode : Node
{
public bool Include = false;
public override NodeType GetNodeType() { return NodeType.PROJECT; }
}
public List<Node> Nodes = new List<Node>();
}
public static String GetSolutionPath(DTE dte)
{
try
{
EnvDTE.Solution solution = dte.Solution;
return solution.FullName;
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
return "N/A";
}
}
public static SolutionStructure GetSolutionVCProjects(DTE dte)
{
return GetProjectStructureRecursive(dte); ;
}
public static SolutionStructure GetProjectStructureRecursive(DTE dte)
{
EnvDTE.Solution solution = dte.Solution;
EnvDTE.Projects solutionProjects = solution.Projects;
List<Guid> guids = new List<Guid>();
SolutionStructure projectStructure = new SolutionStructure();
foreach(Project project in solutionProjects)
{
try
{
if (project.Kind == EnvDTE.Constants.vsProjectKindUnmodeled) // not loaded
{
continue;
}
// check it's a c/c++ project
if (project.CodeModel != null)
{
if (project.CodeModel.Language != CodeModelLanguageConstants.vsCMLanguageVC)
{
continue;
}
}
if (project.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
{
SolutionStructure.ProjectNode projectNode = new SolutionStructure.ProjectNode();
projectNode.Name = project.Name;
projectNode.Project = project;
projectNode.Include = false;
projectStructure.Nodes.Add(projectNode);
}
else
{
SolutionStructure.Node folderNode = GetSubProjects(project);
if (folderNode != null)
{
projectStructure.Nodes.Add(folderNode);
}
else
{
Logging.Logging.LogWarning("Subnode was NULL");
}
}
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
return projectStructure;
}
private static SolutionStructure.Node GetSubProjects(EnvDTE.Project project)
{
ProjectItems projectItems = project.ProjectItems;
List<Project> items = new List<Project>();
try
{
foreach (ProjectItem item in projectItems)
{
Project p = item.Object as Project;
if (p != null)
{
items.Add(p);
}
}
if (items.Count > 0)
{
SolutionStructure.FolderNode folderNode = new SolutionStructure.FolderNode();
folderNode.Name = project.Name;
for (int i = 0; i < items.Count; i++)
{
Project item = items[i];
SolutionStructure.Node subFolderNode = GetSubProjects(item);
if(subFolderNode != null)
{
folderNode.SubNodes.Add(subFolderNode);
}
else
{
Logging.Logging.LogWarning("SubNode was NULL");
}
}
return folderNode;
}
else
{
SolutionStructure.ProjectNode projectNode = new SolutionStructure.ProjectNode();
projectNode.Name = project.Name;
projectNode.Project = project;
projectNode.Include = false;
return projectNode;
}
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
return null;
}
}
// Deprecated: remove when old project parsing is retired
public static List<String> GetSolutionProjectsFullNames(DTE dte)
{
List<String> projectNames = new List<String>();
EnvDTE.Solution solution = dte.Solution;
EnvDTE.Projects projects = solution.Projects;
List<Guid> guids = new List<Guid>();
foreach (EnvDTE.Project project in projects)
{
guids.Add(ProjectUtility.ReloadProject(project));
}
projects = solution.Projects;
foreach (EnvDTE.Project project in projects)
{
projectNames.Add(project.FullName);
}
foreach (Guid guid in guids)
{
ProjectUtility.UnloadProject(guid, dte);
}
return projectNames;
}
public static List<String> GetSolutionLanguages(DTE dte)
{
List<String> languages = new List<String>();
List<Project> projects = GetSolutionProjectList(dte);
foreach (EnvDTE.Project project in projects)
{
if (project.CodeModel != null)
{
string language = project.CodeModel.Language;
languages.Add(language);
}
}
languages = languages.Distinct().ToList();
return languages;
}
public static bool GetSolutionIsSaved(DTE dte)
{
try
{
EnvDTE.Solution solution = dte.Solution;
return solution.Saved;
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
throw e;
}
}
public static List<List<string>> GetConfigurationAndPlatformNames(DTE dte)
{
List<List<string>> result = new List<List<string>>();
List<string> configNames = new List<string>();
List<string> platformNames = new List<string>();
DTE2 dte2 = SolutionUtility.GetDTE2(dte);
if(dte2 == null)
{
return result;
}
EnvDTE80.Solution2 solution = (EnvDTE80.Solution2)dte2.Solution;
if(solution == null)
{
return result;
}
EnvDTE80.SolutionBuild2 solutionBuild = (EnvDTE80.SolutionBuild2)solution.SolutionBuild;
if(solutionBuild == null)
{
return result;
}
try
{
foreach (SolutionConfiguration2 solutionConfiguration in solutionBuild.SolutionConfigurations)
{
foreach (SolutionContext context in solutionConfiguration.SolutionContexts)
{
string configurationName = context.ConfigurationName;
configNames.Add(configurationName);
string platformName = context.PlatformName;
platformNames.Add(platformName);
}
}
configNames = configNames.Distinct().ToList();
platformNames = platformNames.Distinct().ToList();
result.Add(configNames);
result.Add(platformNames);
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
return result;
}
public static DTE2 GetDTE2(DTE dte)
{
try
{
List<DTE2> dte2List = new List<DTE2>();
IRunningObjectTable runningObjectTable = null;
GetRunningObjectTable(0, out runningObjectTable);
IEnumMoniker enumMoniker = null;
runningObjectTable.EnumRunning(out enumMoniker);
enumMoniker.Reset();
IntPtr fetched = IntPtr.Zero;
IMoniker[] moniker = new IMoniker[1];
while (enumMoniker.Next(1, moniker, fetched) == 0)
{
IBindCtx bindCtx = null;
CreateBindCtx(0, out bindCtx);
string displayName = "";
moniker[0].GetDisplayName(bindCtx, null, out displayName);
// add all VisualStudio ROT entries to list
if (displayName.StartsWith("!VisualStudio"))
{
object comObject;
runningObjectTable.GetObject(moniker[0], out comObject);
dte2List.Add((DTE2)comObject);
}
}
// find the correct dte2 instance (each running VS instance has one...)
KeyValuePair<DTE2, int> maxMatch = new KeyValuePair<DTE2, int>(null, 0);
foreach (DTE2 dte2 in dte2List)
{
int m = StringUtility.GetMatchingCharsFromStart(dte.Solution.FullName, dte2.Solution.FullName);
if (m > maxMatch.Value)
{
maxMatch = new KeyValuePair<DTE2, int>(dte2, m);
}
}
return maxMatch.Key;
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
return null;
}
}
static public bool ContainsCFiles(DTE dte)
{
List<Project> projects = GetSolutionProjectList(dte); // dte.Solution.Projects;
foreach (Project project in projects)
{
if(ProjectUtility.ContainsCFiles(project) == true)
{
return true;
}
}
return false;
}
static public List<EnvDTE.Project> GetSolutionProjectList(DTE dte)
{
List<EnvDTE.Project> solutionProjects = new List<EnvDTE.Project>();
try
{
SolutionStructure solutionStructure = GetProjectStructureRecursive(dte);
Stack<SolutionStructure.Node> nodeStack = new Stack<Utility.SolutionUtility.SolutionStructure.Node>();
foreach (SolutionStructure.Node node in solutionStructure.Nodes)
{
nodeStack.Push(node);
}
while (nodeStack.Count > 0)
{
Utility.SolutionUtility.SolutionStructure.Node node = nodeStack.Pop();
string name = node.Name;
if (node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
{
solutionProjects.Add(node.Project);
}
else if (node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
{
Utility.SolutionUtility.SolutionStructure.FolderNode folderNode = node as Utility.SolutionUtility.SolutionStructure.FolderNode;
foreach (Utility.SolutionUtility.SolutionStructure.Node subNode in folderNode.SubNodes)
{
nodeStack.Push(subNode);
}
}
}
return solutionProjects;
}
catch(Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
return new List<EnvDTE.Project>();
}
}
}
}
@@ -0,0 +1,61 @@
using System;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
class StringUtility
{
static public Tuple<int, int> FindFirstRange(string text, string startTag, string endTag)
{
if(startTag.Length > 0 && endTag.Length > 0 && (startTag.Length + endTag.Length) < text.Length)
{
int start = text.IndexOf(startTag);
int end = text.IndexOf(endTag);
// just check wheter both, start and end, are valid and the end tag occurs after the start tag
if(start > -1 && end > -1 && end > start)
{
return new Tuple<int, int>(start, end);
}
}
return null;
}
static public int GetMatchingCharsFromStart(string a, string b)
{
int matchingChars = 0;
if (a != string.Empty)
{
a = a.ToLower();
}
else
{
return matchingChars;
}
if (b != string.Empty)
{
b = b.ToLower();
}
else
{
return matchingChars;
}
for (int i = 0; i < Math.Min(a.Length, b.Length); i++)
{
if (!char.Equals(a[i], b[i]))
{
break;
}
else
{
matchingChars++;
}
}
return matchingChars;
}
}
}
@@ -0,0 +1,36 @@
using System;
namespace CoatiSoftware.SourcetrailPlugin.Utility
{
class SystemUtility
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr SetActiveWindow(IntPtr hWnd);
public static void GetWindowFocus()
{
try
{
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
IntPtr windowHandle = process.MainWindowHandle;
if (windowHandle != null)
{
SetForegroundWindow(windowHandle);
SetActiveWindow(windowHandle);
}
}
catch (Exception e)
{
Logging.Logging.LogError("Exception: " + e.Message);
}
}
public static void OpenWindowsExplorerAtDirectory(string directory)
{
System.Diagnostics.Process.Start(directory);
}
}
}
@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
VS SDK Notes: This resx file contains the resources that will be consumed from your package by Visual Studio.
For example, Visual Studio will attempt to load resource '400' from this resource stream when it needs to
load your package's icon. Because Visual Studio will always look in the VSPackage.resources stream first for
resources it needs, you should put additional resources that Visual Studio will load directly into this resx
file.
Resources that you would like to access directly from your package in a strong-typed fashion should be stored
in Resources.resx or another resx file.
-->
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="110" xml:space="preserve">
<value>SourcetrailPlugin</value>
</data>
<data name="112" xml:space="preserve">
<value>Sourcetrail plugin test</value>
</data>
</root>
@@ -0,0 +1,277 @@
namespace CoatiSoftware.SourcetrailPlugin.Wizard
{
partial class ProjectSetupWindow
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProjectSetupWindow));
this.buttonCancel = new System.Windows.Forms.Button();
this.buttonCreate = new System.Windows.Forms.Button();
this.comboBoxConfiguration = new System.Windows.Forms.ComboBox();
this.comboBoxPlatform = new System.Windows.Forms.ComboBox();
this.labelConfiguration = new System.Windows.Forms.Label();
this.labelPlatform = new System.Windows.Forms.Label();
this.buttonSelectAll = new System.Windows.Forms.Button();
this.labelSelectProject = new System.Windows.Forms.Label();
this.folderBrowserTargetDirectory = new System.Windows.Forms.FolderBrowserDialog();
this.textBoxTargetDirectory = new System.Windows.Forms.TextBox();
this.buttonSelect = new System.Windows.Forms.Button();
this.textBoxFileName = new System.Windows.Forms.TextBox();
this.labelFileName = new System.Windows.Forms.Label();
this.labelFileNameEnding = new System.Windows.Forms.Label();
this.helpProvider1 = new System.Windows.Forms.HelpProvider();
this.comboBoxCStandard = new System.Windows.Forms.ComboBox();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.labelCStandard = new System.Windows.Forms.Label();
this.treeViewProjects = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// buttonCancel
//
this.helpProvider1.SetHelpString(this.buttonCancel, "Abort creation of the CDB");
this.buttonCancel.Location = new System.Drawing.Point(12, 413);
this.buttonCancel.Name = "buttonCancel";
this.helpProvider1.SetShowHelp(this.buttonCancel, true);
this.buttonCancel.Size = new System.Drawing.Size(92, 23);
this.buttonCancel.TabIndex = 9;
this.buttonCancel.Text = "Cancel";
this.toolTip1.SetToolTip(this.buttonCancel, "Abort creation of the CDB");
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// buttonCreate
//
this.helpProvider1.SetHelpString(this.buttonCreate, "Start creation of the CDB");
this.buttonCreate.Location = new System.Drawing.Point(178, 413);
this.buttonCreate.Name = "buttonCreate";
this.helpProvider1.SetShowHelp(this.buttonCreate, true);
this.buttonCreate.Size = new System.Drawing.Size(92, 23);
this.buttonCreate.TabIndex = 8;
this.buttonCreate.Text = "Create";
this.toolTip1.SetToolTip(this.buttonCreate, "Start creation of the CDB");
this.buttonCreate.UseVisualStyleBackColor = true;
this.buttonCreate.Click += new System.EventHandler(this.buttonCreate_Click);
//
// comboBoxConfiguration
//
this.comboBoxConfiguration.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxConfiguration.FormattingEnabled = true;
this.helpProvider1.SetHelpKeyword(this.comboBoxConfiguration, "Build configuration for CDB");
this.helpProvider1.SetHelpString(this.comboBoxConfiguration, "The selected build configuration determines the compile flags for the CDB");
this.comboBoxConfiguration.Location = new System.Drawing.Point(87, 277);
this.comboBoxConfiguration.Name = "comboBoxConfiguration";
this.helpProvider1.SetShowHelp(this.comboBoxConfiguration, true);
this.comboBoxConfiguration.Size = new System.Drawing.Size(183, 21);
this.comboBoxConfiguration.TabIndex = 3;
this.toolTip1.SetToolTip(this.comboBoxConfiguration, "The selected build configuration determines the compile flags for the CDB");
//
// comboBoxPlatform
//
this.comboBoxPlatform.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxPlatform.FormattingEnabled = true;
this.helpProvider1.SetHelpString(this.comboBoxPlatform, "The target platform determines some compiler flags included in the CDB");
this.comboBoxPlatform.Location = new System.Drawing.Point(87, 304);
this.comboBoxPlatform.Name = "comboBoxPlatform";
this.helpProvider1.SetShowHelp(this.comboBoxPlatform, true);
this.comboBoxPlatform.Size = new System.Drawing.Size(183, 21);
this.comboBoxPlatform.TabIndex = 4;
this.toolTip1.SetToolTip(this.comboBoxPlatform, "The target platform determines some compiler flags included in the CDB");
//
// labelConfiguration
//
this.labelConfiguration.AutoSize = true;
this.labelConfiguration.Location = new System.Drawing.Point(12, 280);
this.labelConfiguration.Name = "labelConfiguration";
this.labelConfiguration.Size = new System.Drawing.Size(69, 13);
this.labelConfiguration.TabIndex = 6;
this.labelConfiguration.Text = "Configuration";
//
// labelPlatform
//
this.labelPlatform.AutoSize = true;
this.labelPlatform.Location = new System.Drawing.Point(12, 307);
this.labelPlatform.Name = "labelPlatform";
this.labelPlatform.Size = new System.Drawing.Size(45, 13);
this.labelPlatform.TabIndex = 7;
this.labelPlatform.Text = "Platform";
//
// buttonSelectAll
//
this.helpProvider1.SetHelpString(this.buttonSelectAll, "Select all projects if not all are ticked. Deselect all otherwise");
this.buttonSelectAll.Location = new System.Drawing.Point(178, 248);
this.buttonSelectAll.Name = "buttonSelectAll";
this.helpProvider1.SetShowHelp(this.buttonSelectAll, true);
this.buttonSelectAll.Size = new System.Drawing.Size(92, 23);
this.buttonSelectAll.TabIndex = 2;
this.buttonSelectAll.Text = "De/Select All";
this.toolTip1.SetToolTip(this.buttonSelectAll, "Select all projects if not all are ticked. Deselect all otherwise");
this.buttonSelectAll.UseVisualStyleBackColor = true;
this.buttonSelectAll.Click += new System.EventHandler(this.buttonSelectAll_Click);
//
// labelSelectProject
//
this.labelSelectProject.AutoSize = true;
this.labelSelectProject.Location = new System.Drawing.Point(9, 9);
this.labelSelectProject.Name = "labelSelectProject";
this.labelSelectProject.Size = new System.Drawing.Size(78, 13);
this.labelSelectProject.TabIndex = 9;
this.labelSelectProject.Text = "Select Projects";
this.labelSelectProject.Click += new System.EventHandler(this.label1_Click);
//
// textBoxTargetDirectory
//
this.helpProvider1.SetHelpString(this.textBoxTargetDirectory, "Target directory where the CDB will be stored");
this.textBoxTargetDirectory.Location = new System.Drawing.Point(12, 333);
this.textBoxTargetDirectory.Name = "textBoxTargetDirectory";
this.helpProvider1.SetShowHelp(this.textBoxTargetDirectory, true);
this.textBoxTargetDirectory.Size = new System.Drawing.Size(177, 20);
this.textBoxTargetDirectory.TabIndex = 10;
this.toolTip1.SetToolTip(this.textBoxTargetDirectory, "Target directory where the CDB will be stored");
//
// buttonSelect
//
this.helpProvider1.SetHelpString(this.buttonSelect, "Pick a target directory via folder browser");
this.buttonSelect.Location = new System.Drawing.Point(195, 331);
this.buttonSelect.Name = "buttonSelect";
this.helpProvider1.SetShowHelp(this.buttonSelect, true);
this.buttonSelect.Size = new System.Drawing.Size(75, 23);
this.buttonSelect.TabIndex = 5;
this.buttonSelect.Text = "Browse";
this.toolTip1.SetToolTip(this.buttonSelect, "Pick a target directory via folder browser");
this.buttonSelect.UseVisualStyleBackColor = true;
this.buttonSelect.Click += new System.EventHandler(this.buttonSelect_Click);
//
// textBoxFileName
//
this.textBoxFileName.Location = new System.Drawing.Point(87, 360);
this.textBoxFileName.Name = "textBoxFileName";
this.textBoxFileName.Size = new System.Drawing.Size(148, 20);
this.textBoxFileName.TabIndex = 6;
this.textBoxFileName.TextChanged += new System.EventHandler(this.textBoxFileName_TextChanged);
this.textBoxFileName.Leave += new System.EventHandler(this.textBoxFileName_Leave);
//
// labelFileName
//
this.labelFileName.AutoSize = true;
this.labelFileName.Location = new System.Drawing.Point(12, 363);
this.labelFileName.Name = "labelFileName";
this.labelFileName.Size = new System.Drawing.Size(60, 13);
this.labelFileName.TabIndex = 13;
this.labelFileName.Text = "CDB Name";
//
// labelFileNameEnding
//
this.labelFileNameEnding.AutoSize = true;
this.labelFileNameEnding.Location = new System.Drawing.Point(241, 363);
this.labelFileNameEnding.Name = "labelFileNameEnding";
this.labelFileNameEnding.Size = new System.Drawing.Size(29, 13);
this.labelFileNameEnding.TabIndex = 14;
this.labelFileNameEnding.Text = ".json";
//
// comboBoxCStandard
//
this.comboBoxCStandard.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxCStandard.FormattingEnabled = true;
this.helpProvider1.SetHelpString(this.comboBoxCStandard, "Your Solution contains C Files. Please specify which C standard is to be used for" +
" building.");
this.comboBoxCStandard.Location = new System.Drawing.Point(87, 386);
this.comboBoxCStandard.Name = "comboBoxCStandard";
this.helpProvider1.SetShowHelp(this.comboBoxCStandard, true);
this.comboBoxCStandard.Size = new System.Drawing.Size(183, 21);
this.comboBoxCStandard.TabIndex = 7;
this.toolTip1.SetToolTip(this.comboBoxCStandard, "Your Solution contains C Files. Please specify which C standard is to be used for" +
" building.");
//
// labelCStandard
//
this.labelCStandard.AutoSize = true;
this.labelCStandard.Location = new System.Drawing.Point(12, 389);
this.labelCStandard.Name = "labelCStandard";
this.labelCStandard.Size = new System.Drawing.Size(60, 13);
this.labelCStandard.TabIndex = 16;
this.labelCStandard.Text = "C Standard";
//
// treeViewProjects
//
this.treeViewProjects.CheckBoxes = true;
this.treeViewProjects.Location = new System.Drawing.Point(12, 26);
this.treeViewProjects.Name = "treeViewProjects";
this.treeViewProjects.Size = new System.Drawing.Size(258, 216);
this.treeViewProjects.TabIndex = 17;
this.treeViewProjects.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ProjectCheckList_MouseUp);
this.treeViewProjects.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeViewProjects_NodeCheckChanged);
//
// ProjectSetupWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.ClientSize = new System.Drawing.Size(282, 443);
this.Controls.Add(this.treeViewProjects);
this.Controls.Add(this.labelCStandard);
this.Controls.Add(this.comboBoxCStandard);
this.Controls.Add(this.labelFileNameEnding);
this.Controls.Add(this.labelFileName);
this.Controls.Add(this.textBoxFileName);
this.Controls.Add(this.buttonSelect);
this.Controls.Add(this.textBoxTargetDirectory);
this.Controls.Add(this.labelSelectProject);
this.Controls.Add(this.buttonSelectAll);
this.Controls.Add(this.labelPlatform);
this.Controls.Add(this.labelConfiguration);
this.Controls.Add(this.comboBoxPlatform);
this.Controls.Add(this.comboBoxConfiguration);
this.Controls.Add(this.buttonCreate);
this.Controls.Add(this.buttonCancel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.helpProvider1.SetHelpString(this, "Create a CDB from the current C++ solution.");
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ProjectSetupWindow";
this.helpProvider1.SetShowHelp(this, true);
this.Text = "Create Compilation Database";
this.toolTip1.SetToolTip(this, "Create a CDB from the current C++ solution.");
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.Button buttonCreate;
private System.Windows.Forms.ComboBox comboBoxConfiguration;
private System.Windows.Forms.ComboBox comboBoxPlatform;
private System.Windows.Forms.Label labelConfiguration;
private System.Windows.Forms.Label labelPlatform;
private System.Windows.Forms.Button buttonSelectAll;
private System.Windows.Forms.Label labelSelectProject;
private System.Windows.Forms.FolderBrowserDialog folderBrowserTargetDirectory;
private System.Windows.Forms.TextBox textBoxTargetDirectory;
private System.Windows.Forms.Button buttonSelect;
private System.Windows.Forms.TextBox textBoxFileName;
private System.Windows.Forms.Label labelFileName;
private System.Windows.Forms.Label labelFileNameEnding;
private System.Windows.Forms.HelpProvider helpProvider1;
private System.Windows.Forms.ToolTip toolTip1;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
private System.Windows.Forms.ComboBox comboBoxCStandard;
private System.Windows.Forms.Label labelCStandard;
private System.Windows.Forms.TreeView treeViewProjects;
}
}
@@ -0,0 +1,489 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
namespace CoatiSoftware.SourcetrailPlugin.Wizard
{
public partial class ProjectSetupWindow : Form
{
public class SolutionProject
{
public string _name = "";
public bool _include = false;
public SolutionProject(string name, bool 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 _projectStructure = new Utility.SolutionUtility.SolutionStructure();
public List<string> _configurations = new List<string>();
public List<string> _platforms = new List<string>();
public OnCreateProject _onCreateProject = null;
public string _solutionDirectory = "";
public string _solutionFileName = "foo";
public bool _containsCFiles = false;
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()
{
InitializeComponent();
UpdateGUI();
buttonCreate.Enabled = false;
}
public void UpdateGUI()
{
Logging.Logging.LogInfo("Populating GUI");
InitProjectCheckList();
InitComboBoxConfigurations();
InitComboBoxPlatforms();
InitTextBoxTargetDirectory();
InitTextBoxFileName();
InitComboBoxCStandard();
}
private void InitComboBoxConfigurations()
{
Logging.Logging.LogInfo("Adding " + _configurations.Count.ToString() + " build configurations.");
foreach(string configuration in _configurations)
{
comboBoxConfiguration.Items.Add(configuration);
}
if(comboBoxConfiguration.Items.Count > 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 " + _platforms.Count.ToString() + " target platforms.");
foreach (string platform in _platforms)
{
comboBoxPlatform.Items.Add(platform);
}
if(comboBoxPlatform.Items.Count > 0)
{
if(_cdb != null)
{
int index = comboBoxPlatform.Items.IndexOf(_cdb.PlatformName);
comboBoxPlatform.SelectedIndex = index;
}
else
{
comboBoxPlatform.SelectedIndex = 0;
}
}
}
private void InitProjectCheckList()
{
// way to slow for large projects
//if(_cdb != null)
//{
// _cdb.TryLoadData();
//}
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)
{
TreeNode[] subNodes = GetSubNodes(node as Utility.SolutionUtility.SolutionStructure.FolderNode);
TreeNode treeNode = new TreeNode(node.Name, subNodes);
node.UserData = treeNode;
treeViewProjects.Nodes.Add(treeNode);
}
}
UpdateCreateButtonEnabled();
}
private TreeNode[] GetSubNodes(Utility.SolutionUtility.SolutionStructure.FolderNode folderNode)
{
List<TreeNode> result = new List<TreeNode>();
foreach(Utility.SolutionUtility.SolutionStructure.Node node in folderNode.SubNodes)
{
if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
{
TreeNode treeNode = new TreeNode(node.Name);
node.UserData = treeNode;
result.Add(treeNode);
}
else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
{
TreeNode[] subNodes = GetSubNodes(node as Utility.SolutionUtility.SolutionStructure.FolderNode);
TreeNode treeNode = new TreeNode(node.Name, subNodes);
node.UserData = treeNode;
result.Add(treeNode);
}
}
return result.ToArray();
}
private void InitTextBoxTargetDirectory()
{
Logging.Logging.LogInfo("Setting default target directory: \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(_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(_solutionFileName) + "'");
if(_cdb == null)
{
textBoxFileName.Text = _solutionFileName;
}
else
{
textBoxFileName.Text = _cdb.Name;
}
}
private void InitComboBoxCStandard()
{
if(_containsCFiles == false)
{
Logging.Logging.LogInfo("Hiding C Standard selection");
comboBoxCStandard.Hide();
labelCStandard.Hide();
}
else
{
Logging.Logging.LogInfo("Showing C Standard selection");
comboBoxCStandard.Show();
labelCStandard.Show();
foreach(string standard in _cStandards)
{
comboBoxCStandard.Items.Add(standard);
}
comboBoxCStandard.SelectedIndex = 3;
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
Logging.Logging.LogInfo("Close button pressed. Aborting.");
Close();
}
private void buttonCreate_Click(object sender, EventArgs e)
{
OnCreate();
}
private void OnCreate()
{
Logging.Logging.LogInfo("Create button pressed");
if (_onCreateProject != null)
{
string configurationName = "";
string platformName = "";
configurationName = comboBoxConfiguration.SelectedItem as string;
platformName = comboBoxPlatform.SelectedItem as string;
Logging.Logging.LogInfo("Configuration " + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(configurationName) + "|" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(platformName) + " was selected.");
string targetDir = textBoxTargetDirectory.Text;
if(Directory.Exists(targetDir) && CheckFileNameIsValid(textBoxFileName.Text))
{
if (CheckFileExists())
{
Logging.Logging.LogWarning("A file \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(targetDir + "\\" + textBoxFileName.Text) + "\" already exists.");
DialogResult result = MessageBox.Show("A file of the chosen name already exists. Do you want to replace it?", "Sourcetrail Plugin", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
if(result == DialogResult.No)
{
Logging.Logging.LogInfo("Aborting CDB creation and attempting to make file name unique.");
MakeFileNameUnique();
return;
}
}
string cStandard = "c11";
if(_containsCFiles)
{
cStandard = comboBoxCStandard.SelectedItem as string;
}
Logging.Logging.LogInfo("Setting C standard flag to " + cStandard);
_onCreateProject(GetTreeViewProjectItems(), configurationName, platformName, targetDir, textBoxFileName.Text, cStandard);
Close();
}
else
{
if(Directory.Exists(targetDir) == false)
{
Logging.Logging.LogError("The target directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(targetDir) + "\" does not exist.");
MessageBox.Show("The target directory does not exist.", "Sourcetrail Plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
if (CheckFileNameIsValid(textBoxFileName.Text) == false)
{
Logging.Logging.LogError("The chosen file name \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(textBoxFileName.Text) + "\" is not valid. I'd almost dare to say it's invalid!");
MessageBox.Show("The chosen file name is not valid.", "Sourcetrail Plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
else
{
Logging.Logging.LogError("CDB create callback is not set. Cannot start creating CDB.");
}
}
private bool CheckFileNameIsValid(string fileName)
{
Regex badChars = new Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars())) + "]");
if(badChars.IsMatch(fileName))
{
return false;
}
return true;
}
private bool CheckFileExists()
{
string fileName = textBoxFileName.Text;
string path = textBoxTargetDirectory.Text;
string extension = labelFileNameEnding.Text;
return File.Exists(path + "\\" + fileName + extension);
}
private List<EnvDTE.Project> GetTreeViewProjectItems()
{
List<EnvDTE.Project> solutionProjects = new List<EnvDTE.Project>();
// 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 _projectStructure.Nodes)
{
nodeStack.Push(node);
}
while(nodeStack.Count > 0)
{
Utility.SolutionUtility.SolutionStructure.Node node = nodeStack.Pop();
bool include = (node.UserData as TreeNode).Checked;
string name = node.Name;
if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT
&& (node.UserData as TreeNode).Checked == true)
{
solutionProjects.Add(node.Project);
}
else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
{
Utility.SolutionUtility.SolutionStructure.FolderNode folderNode = node as Utility.SolutionUtility.SolutionStructure.FolderNode;
foreach(Utility.SolutionUtility.SolutionStructure.Node subNode in folderNode.SubNodes)
{
nodeStack.Push(subNode);
}
}
}
return solutionProjects;
}
private void ProjectCheckList_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void buttonSelectAll_Click(object sender, EventArgs e)
{
bool select = false;
// if one or more items are unselected, select all
// otherwise deselect all
for (int i = 0; i < treeViewProjects.Nodes.Count; i++)
{
if (treeViewProjects.Nodes[i].Checked == false)
{
select = true;
}
}
for (int i = 0; i < treeViewProjects.Nodes.Count; i++)
{
treeViewProjects.Nodes[i].Checked = select;
}
UpdateCreateButtonEnabled();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void buttonSelect_Click(object sender, EventArgs e)
{
if(Directory.Exists(textBoxTargetDirectory.Text))
{
folderBrowserTargetDirectory.SelectedPath = textBoxTargetDirectory.Text;
}
folderBrowserTargetDirectory.SelectedPath = textBoxTargetDirectory.Text;
DialogResult result = folderBrowserTargetDirectory.ShowDialog();
string selectedPath = folderBrowserTargetDirectory.SelectedPath;
textBoxTargetDirectory.Text = selectedPath;
}
private void treeViewProjects_NodeCheckChanged(object sender, TreeViewEventArgs e)
{
// treeViewProjects.AfterCheck -= treeViewProjects_NodeCheckChanged;
Stack<TreeNode> nodeStack = new Stack<TreeNode>();
foreach (TreeNode subNode in e.Node.Nodes)
{
nodeStack.Push(subNode);
}
while (nodeStack.Count > 0)
{
var node = nodeStack.Pop();
node.Checked = e.Node.Checked;
//foreach (TreeNode subNode in node.Nodes)
//{
// nodeStack.Push(subNode);
//}
}
// treeViewProjects.AfterCheck += treeViewProjects_NodeCheckChanged;
}
private void textBoxFileName_TextChanged(object sender, EventArgs e)
{
}
private void textBoxFileName_Leave(object sender, EventArgs e)
{
// MakeFileNameUnique();
}
private void MakeFileNameUnique()
{
string fileName = textBoxFileName.Text;
int i = 0;
while (CheckFileExists())
{
++i;
textBoxFileName.Text = fileName + i.ToString();
}
}
private void ProjectCheckList_ItemCheck(object sender, ItemCheckEventArgs e)
{
}
private void ProjectCheckList_Click(object sender, EventArgs e)
{
}
private void ProjectCheckList_MouseUp(object sender, MouseEventArgs e)
{
UpdateCreateButtonEnabled();
}
private void UpdateCreateButtonEnabled()
{
bool anythingChecked = false;
Stack<TreeNode> treeNodes = new Stack<TreeNode>();
foreach(TreeNode node in treeViewProjects.Nodes)
{
treeNodes.Push(node);
}
while(treeNodes.Count > 0)
{
TreeNode node = treeNodes.Pop();
if(node.Nodes.Count <= 0 && node.Checked == true)
{
anythingChecked = true;
}
foreach(TreeNode subNode in node.Nodes)
{
treeNodes.Push(subNode);
}
}
buttonCreate.Enabled = anythingChecked;
}
}
}
@@ -0,0 +1,108 @@
namespace CoatiSoftware.SourcetrailPlugin.Wizard
{
partial class WindowCDBReady
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WindowCDBReady));
this.label_message = new System.Windows.Forms.Label();
this.button_ok = new System.Windows.Forms.Button();
this.button_import = new System.Windows.Forms.Button();
this.button_open = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// label_message
//
this.label_message.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label_message.Location = new System.Drawing.Point(10, 9);
this.label_message.MinimumSize = new System.Drawing.Size(290, 70);
this.label_message.Name = "label_message";
this.label_message.Size = new System.Drawing.Size(290, 70);
this.label_message.TabIndex = 0;
this.label_message.Text = "Message";
//
// button_ok
//
this.button_ok.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.button_ok.Location = new System.Drawing.Point(12, 87);
this.button_ok.Name = "button_ok";
this.button_ok.Size = new System.Drawing.Size(75, 23);
this.button_ok.TabIndex = 1;
this.button_ok.Text = "Finish";
this.button_ok.UseVisualStyleBackColor = true;
this.button_ok.Click += new System.EventHandler(this.button_ok_Click);
//
// button_import
//
this.button_import.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.button_import.Location = new System.Drawing.Point(227, 87);
this.button_import.Name = "button_import";
this.button_import.Size = new System.Drawing.Size(75, 23);
this.button_import.TabIndex = 2;
this.button_import.Text = "Import";
this.button_import.UseVisualStyleBackColor = true;
this.button_import.Click += new System.EventHandler(this.button_import_Click);
//
// button_open
//
this.button_open.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.button_open.Location = new System.Drawing.Point(111, 87);
this.button_open.Name = "button_open";
this.button_open.Size = new System.Drawing.Size(92, 23);
this.button_open.TabIndex = 3;
this.button_open.Text = "Open Folder";
this.button_open.UseVisualStyleBackColor = true;
this.button_open.Click += new System.EventHandler(this.button_open_Click);
//
// WindowCDBReady
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(314, 122);
this.ControlBox = false;
this.Controls.Add(this.button_open);
this.Controls.Add(this.button_import);
this.Controls.Add(this.button_ok);
this.Controls.Add(this.label_message);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(330, 160);
this.Name = "WindowCDBReady";
this.Text = "CDB Ready";
this.Resize += new System.EventHandler(this.WindowCDBReady_Resize);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button_ok;
private System.Windows.Forms.Button button_import;
private System.Windows.Forms.Button button_open;
private System.Windows.Forms.Label label_message;
}
}
@@ -0,0 +1,61 @@
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.SourcetrailPlugin.Wizard
{
public partial class WindowCDBReady : Form
{
private string _message0 = "The CDB ";
private string _message1 = " was created at directory ";
private string _message2 = "Do you want to auto-import it in Sourcetrail now?";
private WindowCreateCDB.CreationResult _creationResult = new WindowCreateCDB.CreationResult();
public WindowCDBReady()
{
InitializeComponent();
label_message.AutoSize = false;
label_message.MaximumSize = new Size((int)((float)MaximumSize.Width * 0.8f), 0);
}
public void setData(WindowCreateCDB.CreationResult creationResult)
{
_creationResult = creationResult;
label_message.Text = _message0 + "'" + creationResult._cdbName + "'" + _message1 + "\"" + creationResult._cdbDirectory + "\".";
label_message.Text += "\n" + _message2;
}
private void button_ok_Click(object sender, EventArgs e)
{
Close();
}
private void button_open_Click(object sender, EventArgs e)
{
Utility.SystemUtility.OpenWindowsExplorerAtDirectory(_creationResult._cdbDirectory);
}
private void button_import_Click(object sender, EventArgs e)
{
string message = Utility.NetworkProtocolUtility.CreateCreateProjectMessage(_creationResult._cdbDirectory + "\\" + _creationResult._cdbName + ".json", _creationResult._headerDirectories);
Utility.AsynchronousClient.Send(message);
Close();
}
private void WindowCDBReady_Resize(object sender, EventArgs e)
{
label_message.MaximumSize = new Size((int)((float)MaximumSize.Width * 0.8f), 0);
}
}
}
@@ -0,0 +1,84 @@
namespace CoatiSoftware.SourcetrailPlugin.Wizard
{
partial class WindowCreateCDB
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WindowCreateCDB));
this.progressBar = new System.Windows.Forms.ProgressBar();
this.labelStatus = new System.Windows.Forms.Label();
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.SuspendLayout();
//
// progressBar
//
this.progressBar.Location = new System.Drawing.Point(12, 12);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(259, 23);
this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
this.progressBar.TabIndex = 0;
//
// labelStatus
//
this.labelStatus.AutoSize = true;
this.labelStatus.Location = new System.Drawing.Point(13, 42);
this.labelStatus.Name = "labelStatus";
this.labelStatus.Size = new System.Drawing.Size(52, 13);
this.labelStatus.TabIndex = 1;
this.labelStatus.Text = "Waiting...";
//
// backgroundWorker1
//
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
//
// WindowCreateCDB
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 63);
this.Controls.Add(this.labelStatus);
this.Controls.Add(this.progressBar);
this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "WindowCreateCDB";
this.Text = "Creating Compilation Data Base";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.WindowCreateCDB_FormClosed);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ProgressBar progressBar;
private System.Windows.Forms.Label labelStatus;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
}
}
@@ -0,0 +1,305 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
namespace CoatiSoftware.SourcetrailPlugin.Wizard
{
public partial class WindowCreateCDB : Form
{
public struct CreationResult
{
public SolutionParser.CompilationDatabase _cdb;
public string _cdbDirectory;
public string _cdbName;
public List<string> _headerDirectories;
}
public delegate void OnFinishedCreatingCDB(CreationResult result);
private OnFinishedCreatingCDB _onFinishedCreateCDB = null;
private List<EnvDTE.Project> _projects = new List<EnvDTE.Project>();
private string _configurationName = "";
private string _platformName = "";
private string _targetDir = "";
private string _fileName = "";
private string _cStandard = "";
private string _solutionDir = "";
private SolutionParser.CompilationDatabase _cdb = null;
CreationResult _result = new CreationResult();
private int _threadCount = 1;
private static object _lockObject = new object();
private static ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim();
public OnFinishedCreatingCDB CallbackOnFinishedCreatingCDB
{
get { return _onFinishedCreateCDB; }
set { _onFinishedCreateCDB = value; }
}
public List<EnvDTE.Project> Projects
{
get { return _projects; }
set { _projects = value; }
}
public string ConfigurationName
{
get { return _configurationName; }
set { _configurationName = value; }
}
public string PlatformName
{
get { return _platformName; }
set { _platformName = value; }
}
public string TargetDir
{
get { return _targetDir; }
set { _targetDir = value; }
}
public string FileName
{
get { return _fileName; }
set { _fileName = value; }
}
public string CStandard
{
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();
progressBar.Maximum = 100;
progressBar.Value = 0;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
public void StartWorking()
{
// Show();
backgroundWorker1.RunWorkerAsync();
}
private CreationResult CreateCDB()
{
CreationResult result = new CreationResult();
result._cdb = null;
result._cdbDirectory = "";
result._cdbName = "";
result._headerDirectories = new List<string>();
SolutionParser.CompilationDatabase cdb = null;
List<string> headerDirectories = new List<string>();
Logging.Logging.LogInfo("Starting to create CDB");
try
{
SolutionParser.SolutionParser._headerDirectories.Clear();
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
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.IncludedProjects.Add(p.Name);
}
cdb.Clean();
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to create CDB: " + e.Message);
}
result._cdb = cdb;
result._cdbDirectory = _targetDir;
result._cdbName = _fileName;
result._headerDirectories = headerDirectories;
Logging.Logging.LogInfo("Done creating CDB");
return result;
}
private SolutionParser.CompilationDatabase CreateCommandObjects()
{
SolutionParser.CompilationDatabase cdb = new SolutionParser.CompilationDatabase();
cdb.Directory = _targetDir;
cdb.Name = _fileName;
File.WriteAllText(_targetDir + "\\" + _fileName + ".json", "");
File.AppendAllText(_targetDir + "\\" + _fileName + ".json", "[\n");
// Mutex commandObjectMutex = new Mutex();
object lockObject = new object();
object lockObject2 = new object();
Utility.QueuedFileWriter fileWriter = new Utility.QueuedFileWriter();
fileWriter.FileName = _fileName + ".json";
fileWriter.TargetDirectory = _targetDir;
fileWriter.startWorking();
try
{
// parallel with tasks
Multitasking.LimitedThreadsTaskScheduler scheduler = new Multitasking.LimitedThreadsTaskScheduler(_threadCount);
TaskFactory factory = new TaskFactory(scheduler);
List<Task> tasks = new List<Task>();
int projectsProcessed = 0;
foreach (EnvDTE.Project project in _projects)
{
string projectName = project.Name;
Logging.Logging.LogInfo("Scheduling " + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(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, false); // since the data is written to file right away now, no need to store it
// the cdb is however still needed to store some meta data later
fileWriter.pushMessage(obj.SerializeJSON() + ",");
}
});
tasks.Add(t);
}
int threadCount = System.Diagnostics.Process.GetCurrentProcess().Threads.Count;
Task.WaitAll(tasks.ToArray());
fileWriter.stopWorking();
backgroundWorker1.ReportProgress(100, "Writing data to file. This might take several minutes...");
}
catch(Exception e)
{
Logging.Logging.LogError("Failed to create CDB: " + e.Message);
}
finally
{
File.AppendAllText(_targetDir + "\\" + _fileName + ".json", "\n]");
}
return cdb;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
_result = CreateCDB();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if(backgroundWorker1.CancellationPending == false)
{
progressBar.Value = e.ProgressPercentage;
labelStatus.Text = e.UserState as string;
}
else
{
progressBar.Value = 0;
labelStatus.Text = "Cancelling...";
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Cancelled == false && e.Error == null /*&& progressBar.Value >= 100*/)
{
if (_onFinishedCreateCDB != null)
{
_onFinishedCreateCDB(_result);
}
}
else
{
Logging.Logging.LogWarning("CDB creation was aborted by user");
}
Close();
}
private void WindowCreateCDB_FormClosed(object sender, FormClosedEventArgs e)
{
backgroundWorker1.CancelAsync();
}
}
}
@@ -0,0 +1,92 @@
namespace CoatiSoftware.SourcetrailPlugin.Wizard
{
partial class WindowMessage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WindowMessage));
this.buttonCancel = new System.Windows.Forms.Button();
this.buttonOK = new System.Windows.Forms.Button();
this.labelContent = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonCancel.Location = new System.Drawing.Point(13, 78);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 0;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// buttonOK
//
this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonOK.Location = new System.Drawing.Point(257, 78);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 1;
this.buttonOK.Text = "OK";
this.buttonOK.UseVisualStyleBackColor = true;
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
//
// labelContent
//
this.labelContent.AutoSize = true;
this.labelContent.Location = new System.Drawing.Point(13, 13);
this.labelContent.MaximumSize = new System.Drawing.Size(300, 0);
this.labelContent.Name = "labelContent";
this.labelContent.Size = new System.Drawing.Size(44, 13);
this.labelContent.TabIndex = 2;
this.labelContent.Text = "Content";
//
// WindowMessage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(344, 113);
this.Controls.Add(this.labelContent);
this.Controls.Add(this.buttonOK);
this.Controls.Add(this.buttonCancel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "WindowMessage";
this.Text = "Message";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.Button buttonOK;
private System.Windows.Forms.Label labelContent;
}
}
@@ -0,0 +1,80 @@
using System;
using System.Windows.Forms;
namespace CoatiSoftware.SourcetrailPlugin.Wizard
{
public partial class WindowMessage : Form
{
private string _title = "Title";
private string _message = "Message";
public delegate void Callback();
private Callback _onOK = null;
private Callback _onCancel = null;
public string Title
{
get { return _title; }
set { _title = value; }
}
public string Message
{
get { return _message; }
set { _message = value; }
}
public Callback OnOK
{
get { return _onOK; }
set { _onOK = value; }
}
public Callback OnCancel
{
get { return _onCancel; }
set { _onCancel = value; }
}
public WindowMessage()
{
InitializeComponent();
}
public void RefreshWindow()
{
Text = _title;
labelContent.Text = _message;
if(_onCancel != null)
{
buttonCancel.Show();
}
else
{
buttonCancel.Hide();
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
if(_onCancel != null)
{
_onCancel();
}
Close();
}
private void buttonOK_Click(object sender, EventArgs e)
{
if(_onOK != null)
{
_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>
@@ -0,0 +1,23 @@
<?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.9.8" Language="en-US" Publisher="Coati Software OG" />
<DisplayName>SourcetrailPlugin</DisplayName>
<Description xml:space="preserve">This package allows Sourcetrail to communicate with Visual Studio and vice versa.</Description>
<MoreInfo>http://www.sourcetrail.com/</MoreInfo>
<ReleaseNotes>Creation of CDBs is in beta and may change in future versions</ReleaseNotes>
<Icon>sourcetrail.ico</Icon>
</Metadata>
<Installation InstalledByMsi="false">
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="11.0" />
<InstallationTarget Version="[12.0,13.0)" Id="Microsoft.VisualStudio.Pro" />
<InstallationTarget Version="[14.0,15.0)" Id="Microsoft.VisualStudio.Community" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="4.5" />
<Dependency Id="Microsoft.VisualStudio.MPF.11.0" DisplayName="Visual Studio MPF 11.0" d:Source="Installed" Version="11.0" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
</Assets>
</PackageManifest>
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

@@ -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