logic: Added plugin Logging
Added plugin file logging and exception handling. Also fixed some reported bugs from the last release version. Updated documentation.
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
-Check latest plugin version is installed
|
||||
-Start VS and load a C/C++ solution (best mixed with multiple projects)
|
||||
-Check all projects are loaded in Solution Explorer
|
||||
-Check Plugin Logging and Obfuscation is off
|
||||
-VS Menu Bar -> Tools -> Options -> Coati -> Logging & Obfuscation is off
|
||||
-Delete log file and dictionary for current VS session if present
|
||||
-delete log file for current session at ..AppData/Local/Coati Software/Plugin/VS if present
|
||||
-delete dictionary file for current session at ..AppData/Local/Coati Software/Plugin/VS if present
|
||||
-Create CDB from solution
|
||||
-Check all C/C++ projects listed in CDB dialogue
|
||||
-Check eventual non-C/C++ projects are not listed
|
||||
@@ -29,25 +34,47 @@
|
||||
-Check finished CDB
|
||||
-check at correct location with correct name
|
||||
-check CDB file is non-empty (at least estimate whether number of lines in CDB coincides with VS solution)
|
||||
-Check no new Log file or Dictionary file was created
|
||||
-Check ..AppData/Local/Coati Software/Plugin/VS for no new log created
|
||||
-Check ..AppData/Local/Coati Software/Plugin/VS for no new dictionary created
|
||||
-Turn on Logging
|
||||
-VS Menu Bar -> Tools -> Options -> Coati -> Logging ON & Obfuscation OFF
|
||||
-Enable VS Output Window
|
||||
-VS Menu Bar -> View -> Output
|
||||
-In Output Window, show Coati log (Show Output from: Coati Log)
|
||||
-Create CDB from solution again
|
||||
-Check location and name is the same as last time
|
||||
-Check dialogue asking whether to overwrite old file or not
|
||||
-Click no
|
||||
-Check number appended to file name
|
||||
-Create CDB with the new name
|
||||
-Check VS Output Window displays messages during creation
|
||||
-Check project- and file names and directories are in clear text
|
||||
-Check finished CDB
|
||||
-check at correct location with correct name
|
||||
-check CDB file is non-empty (at least estimate whether number of lines in CDB coincides with VS solution)
|
||||
-Unload a project in the Solution Explorer
|
||||
-Check new Log file but no Dictionary file was created
|
||||
-Check ..AppData/Local/Coati Software/Plugin/VS for new log created
|
||||
-Check ..AppData/Local/Coati Software/Plugin/VS for no new dictionary created
|
||||
-Turn on Obfuscation
|
||||
-VS Menu Bar -> Tools -> Options -> Coati -> Logging ON & Obfuscation ON
|
||||
-Create CDB from solution again
|
||||
-Check unloaded project is not in the listed projects in the dialogue
|
||||
-Check location and name is the same as first time
|
||||
-Check dialogue asking whether to overwrite old file or not
|
||||
-Click yes
|
||||
-Click Create
|
||||
-Check VS Output Window displays messages during creation
|
||||
-Check project- and file names and directories are obfuscated (a0, b0, c0,...)
|
||||
-Check finished CDB
|
||||
-check at correct location with correct name
|
||||
-check CDB file is smaller now (reduced size has to make sense considering the missing project)
|
||||
-Check new Log entries and Dictionary file was created
|
||||
-Check ..AppData/Local/Coati Software/Plugin/VS for no new log file
|
||||
-Check the log file created in this session at ..AppData/Local/Coati Software/Plugin/VS for new entries
|
||||
-Check new entries are using obfuscated names
|
||||
-Check ..AppData/Local/Coati Software/Plugin/VS for new dictionary created
|
||||
-Create CDB from solution again
|
||||
-Check location and name is the same as first time
|
||||
-Check dialogue asking whether to overwrite old file or not
|
||||
@@ -11,4 +11,9 @@ These Edge Cases should be considered in a dedicated Test Solution for the Plugi
|
||||
-at least two levels deep
|
||||
|
||||
-Include Paths
|
||||
-add at least one include path to Project->Properties->Configuration Properties->VC++ Directories->Include Directories
|
||||
-add at least one include path to Project->Properties->Configuration Properties->VC++ Directories->Include Directories
|
||||
|
||||
-Solution Structure
|
||||
-have a solution with no projects directly under the solution
|
||||
-so: Solution/Folder/Project
|
||||
-no: Solution/Project
|
||||
Binary file not shown.
@@ -129,6 +129,13 @@
|
||||
</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="Utility\FileUtility.cs" />
|
||||
<Compile Include="Guids.cs" />
|
||||
<Compile Include="NetworkProtocolUtility.cs" />
|
||||
@@ -194,7 +201,6 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ClassDiagram1.cd" />
|
||||
<None Include="source.extension.vsixmanifest">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
@@ -217,6 +223,7 @@
|
||||
<IncludeInVSIX>true</IncludeInVSIX>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<PropertyGroup>
|
||||
<UseCodebase>true</UseCodebase>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -16,10 +16,14 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
{
|
||||
private uint _serverPort = 6666;
|
||||
private uint _clientPort = 6667;
|
||||
private bool _logging = false;
|
||||
private bool _obfuscateLogging = false;
|
||||
|
||||
public delegate void Callback();
|
||||
public static Callback _serverPortChangeCallback = null;
|
||||
public static Callback _clientPortChangeCallback = null;
|
||||
public static Callback _loggingToggled = null;
|
||||
public static Callback _obfuscationToggled = null;
|
||||
|
||||
[Category("Coati")]
|
||||
[DisplayName("VS Port")]
|
||||
@@ -53,6 +57,38 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Coati")]
|
||||
[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("Coati")]
|
||||
[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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public OptionPageGrid()
|
||||
{
|
||||
}
|
||||
@@ -91,6 +127,24 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
System.Threading.Thread _serverThread = null;
|
||||
|
||||
public CoatiPluginPackage()
|
||||
@@ -100,12 +154,15 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
InitLogging();
|
||||
InitNetwork();
|
||||
|
||||
Utility.FileUtility._errorCallback = new Utility.FileUtility.ErrorCallback(OnFileUtilityError);
|
||||
|
||||
OptionPageGrid._serverPortChangeCallback = new OptionPageGrid.Callback(OnServerPortChanged);
|
||||
OptionPageGrid._clientPortChangeCallback = new OptionPageGrid.Callback(OnClientPortChanged);
|
||||
OptionPageGrid._loggingToggled = new OptionPageGrid.Callback(OnLoggingToggled);
|
||||
OptionPageGrid._obfuscationToggled = new OptionPageGrid.Callback(OnObfuscationToggled);
|
||||
|
||||
OleMenuCommandService mcs = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
|
||||
if ( null != mcs )
|
||||
@@ -133,10 +190,14 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
|
||||
_solutionEvents.Opened += OnSolutionOpened;
|
||||
_solutionEvents.AfterClosing += OnSolutionClosed;
|
||||
|
||||
Logging.Logging.LogInfo("Initialization done");
|
||||
}
|
||||
|
||||
void OnSolutionOpened()
|
||||
{
|
||||
Logging.Logging.LogInfo("A solution was loaded, checking languages");
|
||||
|
||||
try
|
||||
{
|
||||
DTE dte = (DTE)GetService(typeof(DTE));
|
||||
@@ -148,25 +209,34 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
@@ -174,6 +244,8 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
|
||||
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);
|
||||
@@ -185,6 +257,22 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
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 OnCreateProject(List<EnvDTE.Project> projects, string configurationName, string platformName, string targetDir, string fileName, string cStandard)
|
||||
{
|
||||
Wizard.WindowCreateCDB createCDB = new Wizard.WindowCreateCDB();
|
||||
@@ -195,19 +283,56 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
createCDB.FileName = fileName;
|
||||
createCDB.CStandard = cStandard;
|
||||
|
||||
createCDB.CallbackOnFinishedCreatingCDB = WriteCDBToFile;
|
||||
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)
|
||||
{
|
||||
WriteCDBToFile(creationResult._cdb, creationResult._cdbDirectory, creationResult._cdbName);
|
||||
|
||||
//string message = NetworkProtocolUtility.createCreateProjectMessage(creationResult._cdbDirectory + "\\" + creationResult._cdbName, creationResult._headerDirectories);
|
||||
|
||||
//Utility.AsynchronousClient.Send(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Logging.LogError("Invalid data received");
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteCDBToFile(SolutionParser.CompilationDatabase cdb, string directory, string fileName)
|
||||
{
|
||||
string content = cdb.SerializeJSON();
|
||||
File.WriteAllText(directory + "\\" + fileName + ".json", content);
|
||||
try
|
||||
{
|
||||
string content = cdb.SerializeJSON();
|
||||
File.WriteAllText(directory + "\\" + fileName + ".json", content);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
string foo = "Error";
|
||||
string bar = "Failed to write CDB '" + fileName + "' to directory \"" + directory + "\"\n";
|
||||
bar += "See log for details.";
|
||||
|
||||
Wizard.WindowMessage wm = new Wizard.WindowMessage();
|
||||
wm.Title = foo;
|
||||
wm.Message = bar;
|
||||
wm.RefreshWindow();
|
||||
wm.ShowDialog();
|
||||
|
||||
bar = "Failed to write CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' to directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n";
|
||||
Logging.Logging.LogError(bar);
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
string title = "CDB finished";
|
||||
string message = "The CDB " + fileName + " was created at directory \"" + directory + "\"\n";
|
||||
string message = "The CDB '" + fileName + "' was created at directory \"" + directory + "\"\n";
|
||||
message += "You can now use it in Coati.";
|
||||
|
||||
Wizard.WindowMessage windowMessage = new Wizard.WindowMessage();
|
||||
@@ -215,6 +340,9 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
windowMessage.Message = message;
|
||||
windowMessage.RefreshWindow();
|
||||
windowMessage.ShowDialog();
|
||||
|
||||
message = "The CDB '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(fileName) + "' was created at directory \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(directory) + "\"\n";
|
||||
Logging.Logging.LogInfo(message);
|
||||
}
|
||||
|
||||
private void MenuItemCallback(object sender, EventArgs e)
|
||||
@@ -301,16 +429,20 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
|
||||
private void OnNetworkErrorCallback(string message)
|
||||
{
|
||||
Logging.Logging.LogError("Network Error: " + message.ToString());
|
||||
DisplayMessage("Coati Network Error", message);
|
||||
}
|
||||
|
||||
private void OnFileUtilityError(string message)
|
||||
{
|
||||
Logging.Logging.LogError("File Error: " + message.ToString());
|
||||
DisplayMessage("Coati File Error", message);
|
||||
}
|
||||
|
||||
private void OnServerPortChanged()
|
||||
{
|
||||
Logging.Logging.LogInfo("Changing Server Port to " + ServerPort.ToString());
|
||||
|
||||
Utility.AsynchronousSocketListener._port = ServerPort;
|
||||
|
||||
_serverThread.Abort();
|
||||
@@ -321,9 +453,35 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
|
||||
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));
|
||||
@@ -345,6 +503,8 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CoatiSoftware.CoatiPlugin.Logging
|
||||
{
|
||||
class FileLogger : ILogger
|
||||
{
|
||||
private static string _directory = "";
|
||||
private static string _fileNamePrefix = "Log_CoatiPlugin_";
|
||||
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.CoatiPlugin.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.CoatiPlugin.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.CoatiPlugin.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.CoatiPlugin.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.CoatiPlugin.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_CoatiPlugin_";
|
||||
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.CoatiPlugin.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 == CoatiPlugin.Logging.LogMessage.LogMessageType.INFO)
|
||||
{
|
||||
Debug.WriteLine(message.Message, "Info");
|
||||
WriteToOutputWindow("Info: " + message.Message);
|
||||
}
|
||||
if (message.MessageType == CoatiPlugin.Logging.LogMessage.LogMessageType.WARNING)
|
||||
{
|
||||
Debug.WriteLine(message.Message, "Warning");
|
||||
WriteToOutputWindow("Warning: " + message.Message);
|
||||
}
|
||||
if (message.MessageType == CoatiPlugin.Logging.LogMessage.LogMessageType.ERROR)
|
||||
{
|
||||
Debug.WriteLine(message.Message, "Error");
|
||||
WriteToOutputWindow("Error: " + message.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteToOutputWindow(string message)
|
||||
{
|
||||
string paneName = "Coati 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');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
private static string s_endOfMessageToken = "<EOM>";
|
||||
|
||||
private static string s_createProjectPrefix = "createProject";
|
||||
private static string s_createCDBProjectPrefix = "createCDBProject";
|
||||
private static string s_ideId = "vs";
|
||||
|
||||
public class CursorPosition
|
||||
@@ -86,6 +87,28 @@ namespace CoatiSoftware.CoatiPlugin
|
||||
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_endOfMessageToken;
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public static CursorPosition parseSetCursorMessage(string message)
|
||||
{
|
||||
CursorPosition result = new CursorPosition();
|
||||
|
||||
@@ -19,51 +19,22 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
|
||||
static public List<string> _additionalCompileFlags = new List<string>();
|
||||
|
||||
// Creates a cdb from all projects in the solution
|
||||
// For a more selective approach use 'CreateCommandObjects(...)' for per-project compile commands and assamble the cdb yourself
|
||||
static public CompilationDatabase CreateCompilationDatabase(DTE dte, string configurationName, string platformName)
|
||||
{
|
||||
if(dte == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ReloadAll(dte);
|
||||
|
||||
CompilationDatabase compilationDatabase = new CompilationDatabase();
|
||||
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
|
||||
EnvDTE.Projects projects = solution.Projects;
|
||||
|
||||
foreach (EnvDTE.Project project in projects)
|
||||
{
|
||||
List<CommandObject> cmdObjts = CreateCommandObjects(project, configurationName, platformName, "c11"); // TODO: retrieve real config/platform
|
||||
|
||||
foreach(CommandObject cmdObj in cmdObjts)
|
||||
{
|
||||
compilationDatabase.AddCommandObject(cmdObj);
|
||||
}
|
||||
}
|
||||
|
||||
UnloadReloadedProjects(dte);
|
||||
|
||||
return compilationDatabase;
|
||||
}
|
||||
static public List<string> _headerDirectories = new List<string>();
|
||||
|
||||
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.SolutionUtility.ReloadProject(project);
|
||||
|
||||
string version = dte.Version;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -84,9 +55,11 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
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);
|
||||
CommandObject cmdObj = CreateCommandObject(item, includeDirectories, preprocessorDefinitions, cppStandard, cStandard, configurationName, platformName);
|
||||
if (cmdObj != null)
|
||||
{
|
||||
result.Add(cmdObj);
|
||||
@@ -95,15 +68,19 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
|
||||
if(projectGuid != Guid.Empty)
|
||||
{
|
||||
Utility.SolutionUtility.UnloadProject(projectGuid, dte);
|
||||
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)
|
||||
{
|
||||
List<string> includeDirectories = new List<string>();
|
||||
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>();
|
||||
|
||||
IEnumerable configurations = project.Configurations as IEnumerable;
|
||||
@@ -148,26 +125,42 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
}
|
||||
}
|
||||
|
||||
VCPlatform platform = vcProjectConfig.Platform as VCPlatform;
|
||||
string platformIncludeDirectories = platform.IncludeDirectories;
|
||||
string[] seperatedDirectories = platformIncludeDirectories.Split(';');
|
||||
|
||||
foreach (string directory in seperatedDirectories)
|
||||
try
|
||||
{
|
||||
string resolvedDirectory = ResolveVSMacro(vcProjectConfig, directory);
|
||||
string[] splitResolvedDirectory = resolvedDirectory.Split(';'); // resolved macros might result in concatenated paths
|
||||
VCPlatform platform = vcProjectConfig.Platform as VCPlatform;
|
||||
string platformIncludeDirectories = platform.IncludeDirectories;
|
||||
string[] seperatedDirectories = platformIncludeDirectories.Split(';');
|
||||
|
||||
foreach (string p in splitResolvedDirectory)
|
||||
foreach (string directory in seperatedDirectories)
|
||||
{
|
||||
includeDirectories.Add(p);
|
||||
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...
|
||||
@@ -204,6 +197,8 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
}
|
||||
}
|
||||
|
||||
Logging.Logging.LogInfo("Found " + includeDirectories.Count.ToString() + " include directories and " + preprocessorDefinitions.Count.ToString() + " preprocessor definitions");
|
||||
|
||||
return new Tuple<List<string>, List<string>>(includeDirectories, preprocessorDefinitions);
|
||||
}
|
||||
|
||||
@@ -227,101 +222,146 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
static private CommandObject CreateCommandObject(EnvDTE.ProjectItem item, List<string> includeDirectories, List<string> preprocessorDefinitions, string vcStandard, string cStandard, string configurationName, string platformName)
|
||||
{
|
||||
DTE dte = item.DTE;
|
||||
Logging.Logging.LogInfo("Starting to create Command Object from item '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(item.Name) + "'");
|
||||
|
||||
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
|
||||
try
|
||||
{
|
||||
CommandObject commandObject = new CommandObject();
|
||||
commandObject.File = item.Name;
|
||||
DTE dte = item.DTE;
|
||||
|
||||
// only write source files to cdb, headers are implicit
|
||||
if (CheckIsHeader(item))
|
||||
if (dte == null)
|
||||
{
|
||||
return 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, "Release", "Win32");
|
||||
|
||||
VCFileConfiguration fc = vcFile.GetFileConfigurationForProjectConfiguration(vcConfig);
|
||||
VCCLCompilerTool t = fc.Tool as VCCLCompilerTool;
|
||||
|
||||
string additionalOptions = t.AdditionalOptions;
|
||||
CompileAsOptions compileAs = t.CompileAs; // VCCLCompilerToolShim
|
||||
|
||||
if(additionalOptions == "$(NOINHERIT)")
|
||||
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
|
||||
{
|
||||
additionalOptions = "";
|
||||
}
|
||||
CommandObject commandObject = new CommandObject();
|
||||
commandObject.File = item.Name;
|
||||
|
||||
// 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)
|
||||
// only write source files to cdb, headers are implicit
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
string 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();
|
||||
|
||||
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
|
||||
{
|
||||
vcStandard = "-std=" + cStandard;
|
||||
Logging.Logging.LogInfo("Item discarded, wrong code model");
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
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;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
}
|
||||
|
||||
Logging.Logging.LogError("Failed to create command object.");
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -332,21 +372,28 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
|
||||
string propString = "";
|
||||
|
||||
foreach (Property prop in props)
|
||||
try
|
||||
{
|
||||
string propName = prop.Name;
|
||||
string propValue = prop.Value as String;
|
||||
|
||||
propString += propName + " - " + propValue + "; ";
|
||||
|
||||
if (propName == "ItemType")
|
||||
foreach (Property prop in props)
|
||||
{
|
||||
if (propValue as String == "ClInclude")
|
||||
string propName = prop.Name;
|
||||
string propValue = prop.Value as String;
|
||||
|
||||
propString += propName + " - " + propValue + "; ";
|
||||
|
||||
if (propName == "ItemType")
|
||||
{
|
||||
return true;
|
||||
if (propValue as String == "ClInclude")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -355,15 +402,22 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
{
|
||||
string result = path;
|
||||
|
||||
Tuple<int, int> potentialMacroPosition = Utility.StringUtility.FindFirstRange(path, "$(", ")");
|
||||
|
||||
if (potentialMacroPosition != null)
|
||||
try
|
||||
{
|
||||
string potentialMacro = path.Substring(potentialMacroPosition.Item1, potentialMacroPosition.Item2 - potentialMacroPosition.Item1 + 1);
|
||||
Tuple<int, int> potentialMacroPosition = Utility.StringUtility.FindFirstRange(path, "$(", ")");
|
||||
|
||||
string resolvedMacro = vcProjectConfig.Evaluate(potentialMacro);
|
||||
if (potentialMacroPosition != null)
|
||||
{
|
||||
string potentialMacro = path.Substring(potentialMacroPosition.Item1, potentialMacroPosition.Item2 - potentialMacroPosition.Item1 + 1);
|
||||
|
||||
result = path.Substring(0, potentialMacroPosition.Item1) + resolvedMacro + path.Substring(potentialMacroPosition.Item2 + 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;
|
||||
@@ -378,11 +432,11 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
|
||||
EnvDTE.Projects projects = solution.Projects;
|
||||
List<EnvDTE.Project> projects = Utility.SolutionUtility.GetSolutionProjectList(dte);
|
||||
|
||||
foreach (EnvDTE.Project project in projects)
|
||||
{
|
||||
_reloadedProjectGuids.Add(Utility.SolutionUtility.ReloadProject(project));
|
||||
_reloadedProjectGuids.Add(Utility.ProjectUtility.ReloadProject(project));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,12 +444,14 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
{
|
||||
foreach(Guid guid in _reloadedProjectGuids)
|
||||
{
|
||||
Utility.SolutionUtility.UnloadProject(guid, dte);
|
||||
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)
|
||||
@@ -403,60 +459,88 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
IEnumerable projectTools = vcProjectConfig.Tools as IEnumerable;
|
||||
foreach (Object tool in projectTools)
|
||||
{
|
||||
VCCLCompilerTool compilerTool = tool as VCCLCompilerTool;
|
||||
|
||||
if (compilerTool != null)
|
||||
try
|
||||
{
|
||||
int majorCompilerVersion = GetCLMajorVersion(compilerTool, vcProjectConfig);
|
||||
VCCLCompilerTool compilerTool = tool as VCCLCompilerTool;
|
||||
|
||||
if (majorCompilerVersion > -1)
|
||||
if (compilerTool != null)
|
||||
{
|
||||
_compatibilityVersionFlag = _compatibilityVersionFlagBase + majorCompilerVersion.ToString();
|
||||
return;
|
||||
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)
|
||||
{
|
||||
if(compilerTool == null || vcProjectConfig == null)
|
||||
Logging.Logging.LogInfo("Looking up CL.exe (C++ compiler)");
|
||||
|
||||
if (compilerTool == null || vcProjectConfig == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
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)
|
||||
try
|
||||
{
|
||||
string resolvedDirectory = ResolveVSMacro(vcProjectConfig, directory);
|
||||
string[] splitResolvedDirectory = resolvedDirectory.Split(';'); // resolved macros might result in concatenated paths
|
||||
VCPlatform platform = vcProjectConfig.Platform as VCPlatform;
|
||||
string executableDirectories = platform.ExecutableDirectories;
|
||||
string[] seperatedDirectories = executableDirectories.Split(';');
|
||||
|
||||
foreach(string d in splitResolvedDirectory)
|
||||
List<string> finalDirectories = new List<string>();
|
||||
foreach (string directory in seperatedDirectories)
|
||||
{
|
||||
finalDirectories.Add(d);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string toolPath = compilerTool.ToolPath;
|
||||
|
||||
foreach(string fd in finalDirectories)
|
||||
catch(Exception e)
|
||||
{
|
||||
string path = fd + "\\" + toolPath;
|
||||
|
||||
if(File.Exists(path))
|
||||
{
|
||||
FileVersionInfo info = FileVersionInfo.GetVersionInfo(path);
|
||||
int version = info.FileMajorPart;
|
||||
|
||||
return version;
|
||||
}
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
}
|
||||
|
||||
Logging.Logging.LogWarning("Failed to find C++ compiler tool.");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -472,27 +556,44 @@ namespace CoatiSoftware.CoatiPlugin.SolutionParser
|
||||
|
||||
string result = "";
|
||||
|
||||
IVCRulePropertyStorage rules = vcProjectConfig.Rules.Item("ConfigurationGeneral");
|
||||
IVCRulePropertyStorage rules = null;
|
||||
|
||||
try
|
||||
{
|
||||
rules = vcProjectConfig.Rules.Item("ConfigurationGeneral");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
return "";
|
||||
}
|
||||
|
||||
if (rules != null)
|
||||
{
|
||||
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)
|
||||
try
|
||||
{
|
||||
result = "-std=c++11";
|
||||
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";
|
||||
}
|
||||
}
|
||||
else if (versionNumber < 130) // version 12 (2013)
|
||||
catch(Exception e)
|
||||
{
|
||||
result = "-std=c++14";
|
||||
}
|
||||
else if (versionNumber < 150) // version 14 (2015)
|
||||
{
|
||||
result = "-std=c++14";
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,10 +21,16 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -37,9 +43,14 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,57 +63,75 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//if(_onErrorCallback != null)
|
||||
//{
|
||||
// _onErrorCallback(e.ToString());
|
||||
//}
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AcceptCallback(IAsyncResult ar)
|
||||
{
|
||||
_allDone.Set();
|
||||
try
|
||||
{
|
||||
_allDone.Set();
|
||||
|
||||
Socket listener = (Socket)ar.AsyncState;
|
||||
Socket handler = listener.EndAccept(ar);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
String content = String.Empty;
|
||||
|
||||
StateObject state = (StateObject)ar.AsyncState;
|
||||
Socket handler = state._workSocket;
|
||||
|
||||
int bytesRead = handler.EndReceive(ar);
|
||||
|
||||
if (bytesRead > 0)
|
||||
try
|
||||
{
|
||||
state._stringBuilder.Append(Encoding.ASCII.GetString(state._buffer, 0, bytesRead));
|
||||
string content = String.Empty;
|
||||
|
||||
content = state._stringBuilder.ToString();
|
||||
if (content.IndexOf(_endOfMessageToken) > -1)
|
||||
StateObject state = (StateObject)ar.AsyncState;
|
||||
Socket handler = state._workSocket;
|
||||
|
||||
int bytesRead = handler.EndReceive(ar);
|
||||
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
if (_onReadCallback != null)
|
||||
state._stringBuilder.Append(Encoding.ASCII.GetString(state._buffer, 0, bytesRead));
|
||||
|
||||
content = state._stringBuilder.ToString();
|
||||
if (content.IndexOf(_endOfMessageToken) > -1)
|
||||
{
|
||||
_onReadCallback(content);
|
||||
if (_onReadCallback != null)
|
||||
{
|
||||
_onReadCallback(content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handler.BeginReceive(state._buffer, 0, StateObject._bufferSize, 0, new AsyncCallback(ReadCallback), state);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
byte[] byteData = Encoding.ASCII.GetBytes(data);
|
||||
handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);
|
||||
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)
|
||||
@@ -123,10 +141,12 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
Socket handler = (Socket)ar.AsyncState;
|
||||
|
||||
int bytesSent = handler.EndSend(ar);
|
||||
Console.WriteLine("Sent {0} bytes to client.", bytesSent);
|
||||
Logging.Logging.LogInfo("Sent " + bytesSent.ToString() + " bytes to client.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Excpetion: " + e.Message);
|
||||
|
||||
if (_onErrorCallback != null)
|
||||
{
|
||||
_onErrorCallback(e.ToString());
|
||||
@@ -159,6 +179,9 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
client.EndConnect(ar);
|
||||
client.Shutdown(SocketShutdown.Both);
|
||||
client.Close();
|
||||
|
||||
Logging.Logging.LogWarning("Connection timed out, message was not sent");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -186,6 +209,8 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Excpetion: " + e.Message);
|
||||
|
||||
if (_onErrorCallback != null)
|
||||
{
|
||||
_onErrorCallback(e.ToString());
|
||||
@@ -195,9 +220,16 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
|
||||
private static void Send(Socket client, String data)
|
||||
{
|
||||
byte[] byteData = Encoding.ASCII.GetBytes(data);
|
||||
try
|
||||
{
|
||||
byte[] byteData = Encoding.ASCII.GetBytes(data);
|
||||
|
||||
client.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), client);
|
||||
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)
|
||||
@@ -212,6 +244,8 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Excpetion: " + e.Message);
|
||||
|
||||
if (_onErrorCallback != null)
|
||||
{
|
||||
if (e is ObjectDisposedException)
|
||||
@@ -221,6 +255,7 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
_onErrorCallback(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
using EnvDTE;
|
||||
using Microsoft.VisualStudio;
|
||||
using Microsoft.VisualStudio.Shell;
|
||||
using Microsoft.VisualStudio.Shell.Interop;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -10,17 +14,24 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
{
|
||||
List<ProjectItem> projectItems = GetProjectItems(project);
|
||||
|
||||
foreach (EnvDTE.ProjectItem item in projectItems)
|
||||
try
|
||||
{
|
||||
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
|
||||
foreach (EnvDTE.ProjectItem item in projectItems)
|
||||
{
|
||||
string extension = item.Properties.Item("Extension").Value.ToString();
|
||||
if (extension == ".c")
|
||||
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
|
||||
{
|
||||
return true;
|
||||
string extension = item.Properties.Item("Extension").Value.ToString();
|
||||
if (extension == ".c")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -34,13 +45,13 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
while (itemEnumerator.MoveNext())
|
||||
{
|
||||
ProjectItem currentItem = (ProjectItem)itemEnumerator.Current;
|
||||
items.Add(GetProjectItemsRecursive(currentItem, ref items));
|
||||
items.Add(GetProjectSubItemsRecursive(currentItem, ref items));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
static private ProjectItem GetProjectItemsRecursive(ProjectItem item, ref List<ProjectItem> projectItems)
|
||||
static private ProjectItem GetProjectSubItemsRecursive(ProjectItem item, ref List<ProjectItem> projectItems)
|
||||
{
|
||||
if (item.ProjectItems == null)
|
||||
{
|
||||
@@ -52,10 +63,104 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
while (items.MoveNext())
|
||||
{
|
||||
ProjectItem currentItem = (ProjectItem)items.Current;
|
||||
projectItems.Add(GetProjectItemsRecursive(currentItem, ref projectItems));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,9 +55,18 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
|
||||
public static String GetSolutionPath(DTE dte)
|
||||
{
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
try
|
||||
{
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
|
||||
return solution.FullName;
|
||||
return solution.FullName;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
|
||||
return "N/A";
|
||||
}
|
||||
}
|
||||
|
||||
public static SolutionStructure GetSolutionVCProjects(DTE dte)
|
||||
@@ -76,34 +85,48 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
|
||||
foreach(Project project in solutionProjects)
|
||||
{
|
||||
if(project.Kind == EnvDTE.Constants.vsProjectKindUnmodeled) // not loaded
|
||||
try
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// check it's a c/c++ project
|
||||
if(project.CodeModel != null)
|
||||
{
|
||||
if(project.CodeModel.Language != CodeModelLanguageConstants.vsCMLanguageVC)
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(project.Kind == "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
|
||||
catch(Exception e)
|
||||
{
|
||||
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);
|
||||
|
||||
projectStructure.Nodes.Add(folderNode);
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,41 +138,58 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
ProjectItems projectItems = project.ProjectItems;
|
||||
List<Project> items = new List<Project>();
|
||||
|
||||
foreach (ProjectItem item in projectItems)
|
||||
try
|
||||
{
|
||||
Project p = item.Object as Project;
|
||||
if(p != null)
|
||||
foreach (ProjectItem item in projectItems)
|
||||
{
|
||||
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);
|
||||
folderNode.SubNodes.Add(subFolderNode);
|
||||
Project p = item.Object as Project;
|
||||
if (p != null)
|
||||
{
|
||||
items.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
return folderNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
SolutionStructure.ProjectNode projectNode = new SolutionStructure.ProjectNode();
|
||||
projectNode.Name = project.Name;
|
||||
projectNode.Project = project;
|
||||
projectNode.Include = false;
|
||||
if (items.Count > 0)
|
||||
{
|
||||
SolutionStructure.FolderNode folderNode = new SolutionStructure.FolderNode();
|
||||
folderNode.Name = project.Name;
|
||||
|
||||
return projectNode;
|
||||
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>();
|
||||
@@ -161,7 +201,7 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
|
||||
foreach (EnvDTE.Project project in projects)
|
||||
{
|
||||
guids.Add(ReloadProject(project));
|
||||
guids.Add(ProjectUtility.ReloadProject(project));
|
||||
}
|
||||
|
||||
projects = solution.Projects;
|
||||
@@ -173,45 +213,17 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
|
||||
foreach (Guid guid in guids)
|
||||
{
|
||||
UnloadProject(guid, dte);
|
||||
ProjectUtility.UnloadProject(guid, dte);
|
||||
}
|
||||
|
||||
return projectNames;
|
||||
}
|
||||
|
||||
public static List<List<String>> GetSolutionProjectItems(DTE dte)
|
||||
{
|
||||
List<List<String>> projectItems = new List<List<String>>();
|
||||
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
EnvDTE.Projects projects = solution.Projects;
|
||||
|
||||
foreach (EnvDTE.Project project in projects)
|
||||
{
|
||||
EnvDTE.ProjectItems items = project.ProjectItems;
|
||||
|
||||
List<String> pItems = new List<String>();
|
||||
|
||||
foreach(EnvDTE.ProjectItem item in items)
|
||||
{
|
||||
for (short i = 0; i < item.FileCount; i++)
|
||||
{
|
||||
pItems.Add(item.get_FileNames(i));
|
||||
}
|
||||
}
|
||||
|
||||
projectItems.Add(pItems);
|
||||
}
|
||||
|
||||
return projectItems;
|
||||
}
|
||||
|
||||
public static List<String> GetSolutionLanguages(DTE dte)
|
||||
{
|
||||
List<String> languages = new List<String>();
|
||||
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
EnvDTE.Projects projects = solution.Projects;
|
||||
List<Project> projects = GetSolutionProjectList(dte);
|
||||
|
||||
foreach (EnvDTE.Project project in projects)
|
||||
{
|
||||
@@ -229,9 +241,18 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
|
||||
public static bool GetSolutionIsSaved(DTE dte)
|
||||
{
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
try
|
||||
{
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
|
||||
return solution.Saved;
|
||||
return solution.Saved;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<List<string>> GetConfigurationAndPlatformNames(DTE dte)
|
||||
@@ -259,125 +280,84 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach (SolutionConfiguration2 solutionConfiguration in solutionBuild.SolutionConfigurations)
|
||||
try
|
||||
{
|
||||
foreach (SolutionContext context in solutionConfiguration.SolutionContexts)
|
||||
foreach (SolutionConfiguration2 solutionConfiguration in solutionBuild.SolutionConfigurations)
|
||||
{
|
||||
string configurationName = context.ConfigurationName;
|
||||
configNames.Add(configurationName);
|
||||
foreach (SolutionContext context in solutionConfiguration.SolutionContexts)
|
||||
{
|
||||
string configurationName = context.ConfigurationName;
|
||||
configNames.Add(configurationName);
|
||||
|
||||
string platformName = context.PlatformName;
|
||||
platformNames.Add(platformName);
|
||||
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);
|
||||
}
|
||||
|
||||
configNames = configNames.Distinct().ToList();
|
||||
platformNames = platformNames.Distinct().ToList();
|
||||
|
||||
result.Add(configNames);
|
||||
result.Add(platformNames);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static DTE2 GetDTE2(DTE dte)
|
||||
{
|
||||
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)
|
||||
try
|
||||
{
|
||||
IBindCtx bindCtx = null;
|
||||
CreateBindCtx(0, out bindCtx);
|
||||
List<DTE2> dte2List = new List<DTE2>();
|
||||
|
||||
string displayName = "";
|
||||
moniker[0].GetDisplayName(bindCtx, null, out displayName);
|
||||
// add all VisualStudio ROT entries to list
|
||||
if (displayName.StartsWith("!VisualStudio"))
|
||||
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)
|
||||
{
|
||||
object comObject;
|
||||
runningObjectTable.GetObject(moniker[0], out comObject);
|
||||
dte2List.Add((DTE2)comObject);
|
||||
}
|
||||
}
|
||||
IBindCtx bindCtx = null;
|
||||
CreateBindCtx(0, out bindCtx);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// returns true if the project was reloaded, false if the project did not need to be reloaded
|
||||
static public Guid ReloadProject(Project project)
|
||||
{
|
||||
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)
|
||||
string displayName = "";
|
||||
moniker[0].GetDisplayName(bindCtx, null, out displayName);
|
||||
// add all VisualStudio ROT entries to list
|
||||
if (displayName.StartsWith("!VisualStudio"))
|
||||
{
|
||||
(vsSolution as IVsSolution4).ReloadProject(projectGuid);
|
||||
return projectGuid;
|
||||
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;
|
||||
}
|
||||
|
||||
return Guid.Empty;
|
||||
}
|
||||
|
||||
static public void UnloadProject(Guid guid, DTE dte)
|
||||
{
|
||||
if (dte == null)
|
||||
catch(Exception e)
|
||||
{
|
||||
return;
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
return null;
|
||||
}
|
||||
|
||||
EnvDTE.Solution solution = dte.Solution;
|
||||
|
||||
EnvDTE.Projects projects = solution.Projects;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static public bool ContainsCFiles(DTE dte)
|
||||
@@ -399,35 +379,44 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
{
|
||||
List<EnvDTE.Project> solutionProjects = new List<EnvDTE.Project>();
|
||||
|
||||
SolutionStructure solutionStructure = GetProjectStructureRecursive(dte);
|
||||
|
||||
Stack<SolutionStructure.Node> nodeStack = new Stack<Utility.SolutionUtility.SolutionStructure.Node>();
|
||||
foreach (SolutionStructure.Node node in solutionStructure.Nodes)
|
||||
try
|
||||
{
|
||||
nodeStack.Push(node);
|
||||
}
|
||||
SolutionStructure solutionStructure = GetProjectStructureRecursive(dte);
|
||||
|
||||
while (nodeStack.Count > 0)
|
||||
{
|
||||
Utility.SolutionUtility.SolutionStructure.Node node = nodeStack.Pop();
|
||||
|
||||
string name = node.Name;
|
||||
|
||||
if (node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
|
||||
Stack<SolutionStructure.Node> nodeStack = new Stack<Utility.SolutionUtility.SolutionStructure.Node>();
|
||||
foreach (SolutionStructure.Node node in solutionStructure.Nodes)
|
||||
{
|
||||
solutionProjects.Add(node.Project);
|
||||
nodeStack.Push(node);
|
||||
}
|
||||
else if (node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
|
||||
|
||||
while (nodeStack.Count > 0)
|
||||
{
|
||||
Utility.SolutionUtility.SolutionStructure.FolderNode folderNode = node as Utility.SolutionUtility.SolutionStructure.FolderNode;
|
||||
foreach (Utility.SolutionUtility.SolutionStructure.Node subNode in folderNode.SubNodes)
|
||||
Utility.SolutionUtility.SolutionStructure.Node node = nodeStack.Pop();
|
||||
|
||||
string name = node.Name;
|
||||
|
||||
if (node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
|
||||
{
|
||||
nodeStack.Push(subNode);
|
||||
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;
|
||||
return solutionProjects;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logging.Logging.LogError("Exception: " + e.Message);
|
||||
|
||||
return new List<EnvDTE.Project>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,20 @@ namespace CoatiSoftware.CoatiPlugin.Utility
|
||||
|
||||
public static void GetWindowFocus()
|
||||
{
|
||||
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
|
||||
IntPtr windowHandle = process.MainWindowHandle;
|
||||
|
||||
if (windowHandle != null)
|
||||
try
|
||||
{
|
||||
SetForegroundWindow(windowHandle);
|
||||
SetActiveWindow(windowHandle);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
|
||||
public void UpdateGUI()
|
||||
{
|
||||
Logging.Logging.LogInfo("Populating GUI");
|
||||
|
||||
InitProjectCheckList();
|
||||
InitComboBoxConfigurations();
|
||||
InitComboBoxPlatforms();
|
||||
@@ -66,6 +68,8 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
|
||||
private void InitComboBoxConfigurations()
|
||||
{
|
||||
Logging.Logging.LogInfo("Adding " + m_configurations.Count.ToString() + " build configurations.");
|
||||
|
||||
foreach(string configuration in m_configurations)
|
||||
{
|
||||
comboBoxConfiguration.Items.Add(configuration);
|
||||
@@ -79,7 +83,9 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
|
||||
private void InitComboBoxPlatforms()
|
||||
{
|
||||
foreach(string platform in m_platforms)
|
||||
Logging.Logging.LogInfo("Adding " + m_platforms.Count.ToString() + " target platforms.");
|
||||
|
||||
foreach (string platform in m_platforms)
|
||||
{
|
||||
comboBoxPlatform.Items.Add(platform);
|
||||
}
|
||||
@@ -141,6 +147,8 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
|
||||
private void InitTextBoxTargetDirectory()
|
||||
{
|
||||
Logging.Logging.LogInfo("Setting default target directory: \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(m_solutionDirectory) + "\"");
|
||||
|
||||
folderBrowserTargetDirectory.SelectedPath = m_solutionDirectory;
|
||||
string rootDirectory = folderBrowserTargetDirectory.SelectedPath.ToString();
|
||||
textBoxTargetDirectory.Text = rootDirectory;
|
||||
@@ -148,20 +156,24 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
|
||||
private void InitTextBoxFileName()
|
||||
{
|
||||
textBoxFileName.Text = m_solutionFileName;
|
||||
Logging.Logging.LogInfo("Setting default file name: '" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(m_solutionFileName) + "'");
|
||||
|
||||
// MakeFileNameUnique();
|
||||
textBoxFileName.Text = m_solutionFileName;
|
||||
}
|
||||
|
||||
private void InitComboBoxCStandard()
|
||||
{
|
||||
if(m_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();
|
||||
|
||||
@@ -176,6 +188,8 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
|
||||
private void buttonCancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
Logging.Logging.LogInfo("Close button pressed. Aborting.");
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -186,6 +200,8 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
|
||||
private void OnCreate()
|
||||
{
|
||||
Logging.Logging.LogInfo("Create button pressed");
|
||||
|
||||
if (m_onCreateProject != null)
|
||||
{
|
||||
string configurationName = "";
|
||||
@@ -194,16 +210,21 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
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?", "Coati Plugin", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||
|
||||
if(result == DialogResult.No)
|
||||
{
|
||||
Logging.Logging.LogInfo("Aborting CDB creation and attempting to make file name unique.");
|
||||
MakeFileNameUnique();
|
||||
return;
|
||||
}
|
||||
@@ -215,6 +236,8 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
cStandard = comboBoxCStandard.SelectedItem as string;
|
||||
}
|
||||
|
||||
Logging.Logging.LogInfo("Setting C standard flag to " + cStandard);
|
||||
|
||||
m_onCreateProject(GetTreeViewProjectItems(), configurationName, platformName, targetDir, textBoxFileName.Text, cStandard);
|
||||
Close();
|
||||
}
|
||||
@@ -222,15 +245,21 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
{
|
||||
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.", "Coati 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.", "Coati Plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Logging.LogError("CDB create callback is not set. Cannot start creating CDB.");
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckFileNameIsValid(string fileName)
|
||||
|
||||
@@ -12,7 +12,15 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
{
|
||||
public partial class WindowCreateCDB : Form
|
||||
{
|
||||
public delegate void OnFinishedCreatingCDB(SolutionParser.CompilationDatabase cdb, string directory, string fileName);
|
||||
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 m_onFinishedCreateCDB = null;
|
||||
|
||||
@@ -24,7 +32,7 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
string m_fileName = "";
|
||||
string m_cStandard = "";
|
||||
|
||||
SolutionParser.CompilationDatabase m_cdb = null;
|
||||
CreationResult m_result = new CreationResult();
|
||||
|
||||
public OnFinishedCreatingCDB CallbackOnFinishedCreatingCDB
|
||||
{
|
||||
@@ -86,18 +94,30 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
backgroundWorker1.RunWorkerAsync();
|
||||
}
|
||||
|
||||
private SolutionParser.CompilationDatabase CreateCDB()
|
||||
private CreationResult CreateCDB()
|
||||
{
|
||||
CreationResult result = new CreationResult();
|
||||
result._cdb = null;
|
||||
result._cdbDirectory = "";
|
||||
result._cdbName = "";
|
||||
result._headerDirectories = new List<string>();
|
||||
|
||||
Logging.Logging.LogInfo("Starting to create CDB");
|
||||
|
||||
SolutionParser.CompilationDatabase cdb = new SolutionParser.CompilationDatabase();
|
||||
|
||||
int projectsProcessed = 0;
|
||||
|
||||
List<string> headerDirectories = new List<string>();
|
||||
SolutionParser.SolutionParser._headerDirectories.Clear();
|
||||
|
||||
foreach (EnvDTE.Project project in m_projects)
|
||||
{
|
||||
List<SolutionParser.CommandObject> commandObjects = SolutionParser.SolutionParser.CreateCommandObjects(project, m_configurationName, m_platformName, m_cStandard);
|
||||
|
||||
projectsProcessed++;
|
||||
float relativProgress = (float)projectsProcessed/(float)m_projects.Count;
|
||||
Logging.Logging.LogInfo("Processing project \"" + Logging.Obfuscation.NameObfuscator.GetObfuscatedName(project.Name) + "\"");
|
||||
backgroundWorker1.ReportProgress((int)(relativProgress * 100), "Processing project \"" + project.Name + "\"");
|
||||
|
||||
foreach (SolutionParser.CommandObject obj in commandObjects)
|
||||
@@ -106,30 +126,52 @@ namespace CoatiSoftware.CoatiPlugin.Wizard
|
||||
}
|
||||
}
|
||||
|
||||
return cdb;
|
||||
headerDirectories = SolutionParser.SolutionParser._headerDirectories;
|
||||
|
||||
result._cdb = cdb;
|
||||
result._cdbDirectory = m_targetDir;
|
||||
result._cdbName = m_fileName;
|
||||
result._headerDirectories = headerDirectories;
|
||||
|
||||
Logging.Logging.LogInfo("Done creating CDB");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
m_cdb = CreateCDB();
|
||||
m_result = CreateCDB();
|
||||
}
|
||||
|
||||
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
||||
{
|
||||
progressBar.Value = e.ProgressPercentage;
|
||||
|
||||
labelStatus.Text = e.UserState as string;
|
||||
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)
|
||||
if(e.Cancelled == false && e.Error == null && progressBar.Value >= 100)
|
||||
{
|
||||
if (m_onFinishedCreateCDB != null)
|
||||
{
|
||||
m_onFinishedCreateCDB(m_cdb, m_targetDir, m_fileName);
|
||||
m_onFinishedCreateCDB(m_result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Logging.LogWarning("CDB creation was aborted by user");
|
||||
}
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
|
||||
<Metadata>
|
||||
<Identity Id="acf15780-03b5-440e-a41e-db79b7043fc2" Version="0.8.12" Language="en-US" Publisher="Coati Software OG" />
|
||||
<Identity Id="acf15780-03b5-440e-a41e-db79b7043fc2" Version="0.8.18" Language="en-US" Publisher="Coati Software OG" />
|
||||
<DisplayName>CoatiPlugin</DisplayName>
|
||||
<Description xml:space="preserve">This package allows Coati to communicate with Visual Studio and vice versa.</Description>
|
||||
<MoreInfo>https://www.coati.io/</MoreInfo>
|
||||
|
||||
Reference in New Issue
Block a user