logic: vs plugin upgrade beta

Added CDB creation
This commit is contained in:
wrongway88
2016-10-13 20:48:06 +02:00
parent 1f904620ae
commit 2dc9995cc1
34 changed files with 6608 additions and 651 deletions
+59
View File
@@ -0,0 +1,59 @@
-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
-Create CDB from solution
-Check all C/C++ projects listed in CDB dialogue
-Check eventual non-C/C++ projects are not listed
-Check all projects unselected
-Check 'Create' Button is disabled
-Select one project
-Check 'Create' Button is enabled
-Click 'De/Select All'
-Check all projects selected
-Click 'De/Select All'
-Check no project selected
-Click 'De/Select All'
-Check all projects selected
-Check all Solution Configurations are listed in the Configuration dropdown
-Check all Solution Platforms are listed in the Platform dropdown
-Copy target location to clip board
-Click 'Browse'
-Check Folder Browser opens
-Select a different folder
-Check target folder field changed to selected folder
-Paste old target location
-Reopen Folder Browser and check it's set to old target location
-Click Create
-Wait for CDB to be finished
-check progress bar shows progress
-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)
-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 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
-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 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)
-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
-Click no
-Check number appended to file name
-Check number is one higher than number from 2nd CDB
-Click Create
-Close Progress Bar before CDB is finished
-Check no new CDB was created
+14
View File
@@ -0,0 +1,14 @@
These Edge Cases should be considered in a dedicated Test Solution for the Plugin
-Non C/C++ Projects
-include projects that are not C/C++ based
-those should be ignored by the plugin
-not show up in the project list when creating a CDB
-not show up in the resulting CDB
-Solution Folders
-the solution should include Solution Folders with Projects inside
-at least two levels deep
-Include Paths
-add at least one include path to Project->Properties->Configuration Properties->VC++ Directories->Include Directories
@@ -53,10 +53,16 @@
<Reference Include="Microsoft.VisualStudio.Shell.Interop.11.0">
<EmbedInteropTypes>true</EmbedInteropTypes>
</Reference>
<Reference Include="Microsoft.VisualStudio.TemplateWizardInterface, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.VisualStudio.TextManager.Interop" />
<Reference Include="Microsoft.VisualStudio.Shell.11.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.10.0" />
<Reference Include="Microsoft.VisualStudio.Shell.Immutable.11.0" />
<Reference Include="Microsoft.VisualStudio.VCProjectEngine, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
@@ -64,6 +70,7 @@
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<COMReference Include="EnvDTE">
@@ -122,10 +129,10 @@
</COMReference>
</ItemGroup>
<ItemGroup>
<Compile Include="FileUtility.cs" />
<Compile Include="Utility\FileUtility.cs" />
<Compile Include="Guids.cs" />
<Compile Include="NetworkProtocolUtility.cs" />
<Compile Include="NetworkUtility.cs" />
<Compile Include="Utility\NetworkUtility.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@@ -137,8 +144,31 @@
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PkgCmdID.cs" />
<Compile Include="SolutionUtility.cs" />
<Compile Include="SystemUtility.cs" />
<Compile Include="SolutionParser\CommandObject.cs" />
<Compile Include="SolutionParser\CompilationDatabase.cs" />
<Compile Include="SolutionParser\SolutionParser.cs" />
<Compile Include="Utility\ProjectUtility.cs" />
<Compile Include="Utility\SolutionUtility.cs" />
<Compile Include="Utility\SystemUtility.cs" />
<Compile Include="Utility\StringUtility.cs" />
<Compile Include="Wizard\WindowCreateCDB.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Wizard\WindowCreateCDB.Designer.cs">
<DependentUpon>WindowCreateCDB.cs</DependentUpon>
</Compile>
<Compile Include="Wizard\ProjectSetupWindow.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Wizard\ProjectSetupWindow.Designer.cs">
<DependentUpon>ProjectSetupWindow.cs</DependentUpon>
</Compile>
<Compile Include="Wizard\WindowMessage.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Wizard\WindowMessage.Designer.cs">
<DependentUpon>WindowMessage.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
@@ -151,8 +181,20 @@
<ManifestResourceName>VSPackage</ManifestResourceName>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Wizard\WindowCreateCDB.resx">
<DependentUpon>WindowCreateCDB.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Wizard\ProjectSetupWindow.resx">
<DependentUpon>ProjectSetupWindow.cs</DependentUpon>
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>ProjectSetupWindow1.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Wizard\WindowMessage.resx">
<DependentUpon>WindowMessage.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="ClassDiagram1.cd" />
<None Include="source.extension.vsixmanifest">
<SubType>Designer</SubType>
</None>
@@ -2,12 +2,12 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<StartAction>Program</StartAction>
<StartProgram>C:\Program Files %28x86%29\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe</StartProgram>
<StartProgram>C:\Program Files %28x86%29\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe</StartProgram>
<StartArguments>/rootsuffix Exp</StartArguments>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<StartAction>Program</StartAction>
<StartProgram>C:\Program Files %28x86%29\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe</StartProgram>
<StartProgram>C:\Program Files %28x86%29\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe</StartProgram>
<StartArguments>/rootsuffix Exp</StartArguments>
</PropertyGroup>
</Project>
@@ -74,6 +74,14 @@
</Strings>
</Button>
<Button guid="guidCoatiPluginCmdSet" id="cmdidCoatiCreateCDB" priority="0x0100" type="Button">
<Parent guid="guidCoatiPluginCmdSet" id="SubMenu" />
<Icon guid="icon" id="icon0" />
<Strings>
<ButtonText>Create CDB (Beta)</ButtonText>
</Strings>
</Button>
</Buttons>
<Menus>
@@ -107,6 +115,7 @@
<IDSymbol name="cmdidCoatiGetActiveLineNumber" value="0x0103"/>
<IDSymbol name="cmdidCoatiSetActiveToken" value="0x0104"/>
<IDSymbol name="cmdidCoatiCreateProject" value="0x0105"/>
<IDSymbol name="cmdidCoatiCreateCDB" value="0x0106"/>
<IDSymbol name="TopLevelMenu" value="0x1021"/>
<IDSymbol name="SubMenu" value="0x1022"/>
</GuidSymbol>
@@ -1,25 +1,14 @@
using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using System.IO;
using EnvDTE;
using EnvDTE80;
using System.Windows.Forms;
// using System.Windows.Forms.
namespace CoatiSoftware.CoatiPlugin
{
@@ -80,6 +69,7 @@ namespace CoatiSoftware.CoatiPlugin
{
private MenuCommand _menuItemSetActiveToken = null;
private MenuCommand _menuItemCreateProject = null;
private MenuCommand _menuItemCreateCDB = null;
private SolutionEvents _solutionEvents = null;
@@ -112,7 +102,7 @@ namespace CoatiSoftware.CoatiPlugin
InitNetwork();
FileUtility._errorCallback = new FileUtility.ErrorCallback(OnFileUtilityError);
Utility.FileUtility._errorCallback = new Utility.FileUtility.ErrorCallback(OnFileUtilityError);
OptionPageGrid._serverPortChangeCallback = new OptionPageGrid.Callback(OnServerPortChanged);
OptionPageGrid._clientPortChangeCallback = new OptionPageGrid.Callback(OnClientPortChanged);
@@ -122,15 +112,19 @@ namespace CoatiSoftware.CoatiPlugin
{
CommandID setActiveTokenCommandID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiSetActiveToken);
CommandID createProjectID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiCreateProject); // cmdidCoatiCreateProject
CommandID createCDBID = new CommandID(GuidList.guidCoatiPluginCmdSet, (int)PkgCmdIDList.cmdidCoatiCreateCDB);
_menuItemSetActiveToken = new MenuCommand(MenuItemCallback, setActiveTokenCommandID);
_menuItemCreateProject = new MenuCommand(MenuItemCallback, createProjectID);
_menuItemCreateCDB = new MenuCommand(MenuItemCallback, createCDBID);
_menuItemCreateProject.Enabled = false;
_menuItemSetActiveToken.Enabled = false;
_menuItemCreateCDB.Enabled = false;
mcs.AddCommand(_menuItemSetActiveToken);
mcs.AddCommand(_menuItemCreateProject);
mcs.AddCommand(_menuItemCreateCDB);
}
DTE dte = (DTE)GetService(typeof(DTE));
@@ -146,7 +140,7 @@ namespace CoatiSoftware.CoatiPlugin
try
{
DTE dte = (DTE)GetService(typeof(DTE));
List<String> languages = SolutionUtility.GetSolutionLanguages(dte);
List<String> languages = Utility.SolutionUtility.GetSolutionLanguages(dte);
bool enable = false;
foreach (String language in languages)
@@ -162,6 +156,7 @@ namespace CoatiSoftware.CoatiPlugin
{
_menuItemSetActiveToken.Enabled = true;
_menuItemCreateProject.Enabled = true;
_menuItemCreateCDB.Enabled = true;
}
}
catch(Exception e)
@@ -174,22 +169,53 @@ namespace CoatiSoftware.CoatiPlugin
{
_menuItemSetActiveToken.Enabled = false;
_menuItemCreateProject.Enabled = false;
_menuItemCreateCDB.Enabled = false;
}
private void InitNetwork()
{
AsynchronousSocketListener._port = ServerPort;
AsynchronousSocketListener server = new AsynchronousSocketListener();
AsynchronousSocketListener._onReadCallback = new AsynchronousSocketListener.OnReadCallback(OnNetworkReadCallback);
AsynchronousSocketListener._onErrorCallback = new AsynchronousSocketListener.OnReadCallback(OnNetworkErrorCallback);
Utility.AsynchronousSocketListener._port = ServerPort;
Utility.AsynchronousSocketListener server = new Utility.AsynchronousSocketListener();
Utility.AsynchronousSocketListener._onReadCallback = new Utility.AsynchronousSocketListener.OnReadCallback(OnNetworkReadCallback);
Utility.AsynchronousSocketListener._onErrorCallback = new Utility.AsynchronousSocketListener.OnReadCallback(OnNetworkErrorCallback);
_serverThread = new System.Threading.Thread(server.DoWork);
_serverThread.Start();
AsynchronousClient._port = ClientPort;
AsynchronousClient._onErrorCallback = new AsynchronousSocketListener.OnReadCallback(OnNetworkErrorCallback);
Utility.AsynchronousClient._port = ClientPort;
Utility.AsynchronousClient._onErrorCallback = new Utility.AsynchronousSocketListener.OnReadCallback(OnNetworkErrorCallback);
}
private void OnCreateProject(List<EnvDTE.Project> projects, string configurationName, string platformName, string targetDir, string fileName, string cStandard)
{
Wizard.WindowCreateCDB createCDB = new Wizard.WindowCreateCDB();
createCDB.Projects = projects;
createCDB.ConfigurationName = configurationName;
createCDB.PlatformName = platformName;
createCDB.TargetDir = targetDir;
createCDB.FileName = fileName;
createCDB.CStandard = cStandard;
createCDB.CallbackOnFinishedCreatingCDB = WriteCDBToFile;
createCDB.StartWorking();
createCDB.ShowDialog();
}
private void WriteCDBToFile(SolutionParser.CompilationDatabase cdb, string directory, string fileName)
{
string content = cdb.SerializeJSON();
File.WriteAllText(directory + "\\" + fileName + ".json", content);
string title = "CDB finished";
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();
windowMessage.Title = title;
windowMessage.Message = message;
windowMessage.RefreshWindow();
windowMessage.ShowDialog();
}
private void MenuItemCallback(object sender, EventArgs e)
{
@@ -201,44 +227,62 @@ namespace CoatiSoftware.CoatiPlugin
{
if (menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidCoatiSetActiveToken)
{
string fileName = FileUtility.GetActiveDocumentName(dte);
string filePath = FileUtility.GetActiveDocumentPath(dte);
string fileName = Utility.FileUtility.GetActiveDocumentName(dte);
string filePath = Utility.FileUtility.GetActiveDocumentPath(dte);
int lineNumber = FileUtility.GetActiveLineNumber(dte);
int columnNumber = FileUtility.GetActiveColumnNumber(dte);
int lineNumber = Utility.FileUtility.GetActiveLineNumber(dte);
int columnNumber = Utility.FileUtility.GetActiveColumnNumber(dte);
string message = NetworkProtocolUtility.createActivateTokenMessage(filePath + fileName, lineNumber, columnNumber);
AsynchronousClient.Send(message);
Utility.AsynchronousClient.Send(message);
}
else if(menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidCoatiCreateCDB)
{
CreateCompilationDatabase(dte);
}
else if(menuCommand.CommandID.ID == (int)PkgCmdIDList.cmdidCoatiCreateProject)
{
string solutionName = SolutionUtility.GetSolutionPath(dte);
// CreateCoatiProjectOld();
if(solutionName == "")
{
List<string> items = SolutionUtility.GetSolutionProjectsFullNames(dte);
if(items.Count > 0)
{
solutionName = items[0];
}
}
if(solutionName.Length > 0)
{
string message = NetworkProtocolUtility.createCreateProjectMessage(solutionName);
AsynchronousClient.Send(message);
}
else
{
DisplayMessage("Coati", "Can not create a Coati Project. Please check whether your VS solution is a valid C or C++ solution and is saved.");
}
Wizard.WindowMessage windowMessage = new Wizard.WindowMessage();
windowMessage.Title = "Hint";
windowMessage.Message = "Consider using 'Create CDB' if errors arise during Coati's indexing. This will become standard in the future.";
windowMessage.OnOK = CreateCoatiProjectOld;
windowMessage.RefreshWindow();
windowMessage.ShowDialog();
}
}
}
private void CreateCoatiProjectOld()
{
DTE dte = (DTE)GetService(typeof(DTE));
string solutionName = Utility.SolutionUtility.GetSolutionPath(dte);
if (solutionName == "") // TODO: make a better fallback for non-existant solution
{
List<string> items = Utility.SolutionUtility.GetSolutionProjectsFullNames(dte);
if (items.Count > 0)
{
solutionName = items[0];
}
}
if (solutionName.Length > 0)
{
string message = NetworkProtocolUtility.createCreateProjectMessage(solutionName);
Utility.AsynchronousClient.Send(message);
}
else
{
DisplayMessage("Coati", "Can not create a Coati Project. Please check whether your VS solution is a valid C or C++ solution and is saved.");
}
}
private void OnNetworkReadCallback(string message)
{
NetworkProtocolUtility.CursorPosition cursorPosition = NetworkProtocolUtility.parseSetCursorMessage(message);
@@ -246,11 +290,11 @@ namespace CoatiSoftware.CoatiPlugin
{
cursorPosition.ColumnNumber += 1; // VS counts columns starting at 1, coati starts at 0
DTE dte = (DTE)GetService(typeof(DTE));
if (FileUtility.OpenSourceFile(dte, cursorPosition.FilePath))
if (Utility.FileUtility.OpenSourceFile(dte, cursorPosition.FilePath))
{
FileUtility.GoToLine(dte, cursorPosition.LineNumber, cursorPosition.ColumnNumber);
Utility.FileUtility.GoToLine(dte, cursorPosition.LineNumber, cursorPosition.ColumnNumber);
SystemUtility.GetWindowFocus();
Utility.SystemUtility.GetWindowFocus();
}
}
}
@@ -267,17 +311,17 @@ namespace CoatiSoftware.CoatiPlugin
private void OnServerPortChanged()
{
AsynchronousSocketListener._port = ServerPort;
Utility.AsynchronousSocketListener._port = ServerPort;
_serverThread.Abort();
AsynchronousSocketListener server = new AsynchronousSocketListener();
Utility.AsynchronousSocketListener server = new Utility.AsynchronousSocketListener();
_serverThread = new System.Threading.Thread(server.DoWork);
_serverThread.Start();
}
private void OnClientPortChanged()
{
AsynchronousClient._port = ClientPort;
Utility.AsynchronousClient._port = ClientPort;
}
private void DisplayMessage(string title, string message)
@@ -298,5 +342,32 @@ namespace CoatiSoftware.CoatiPlugin
0, // false
out result));
}
private void CreateCompilationDatabase(DTE dte)
{
Wizard.ProjectSetupWindow window = new Wizard.ProjectSetupWindow();
Utility.SolutionUtility.SolutionStructure projectStructure = Utility.SolutionUtility.GetSolutionVCProjects(dte);
List<List<string>> configsAndPlatforms = Utility.SolutionUtility.GetConfigurationAndPlatformNames(dte);
window.m_projectStructure = projectStructure;
window.m_configurations = configsAndPlatforms[0];
window.m_platforms = configsAndPlatforms[1];
string directory = System.IO.Path.GetDirectoryName(dte.Solution.FullName);
window.m_solutionDirectory = directory;
string solutionName = System.IO.Path.GetFileNameWithoutExtension(dte.Solution.FullName);
window.m_solutionFileName = solutionName;
bool containsCFiles = true; // Utility.SolutionUtility.ContainsCFiles(dte); // takes ridiculously long
window.m_containsCFiles = containsCFiles;
window.UpdateGUI();
window.m_onCreateProject = OnCreateProject;
window.ShowDialog();
}
}
}
@@ -8,5 +8,6 @@ namespace CoatiSoftware.CoatiPlugin
{
public const uint cmdidCoatiSetActiveToken = 0x104;
public const uint cmdidCoatiCreateProject = 0x105;
public const uint cmdidCoatiCreateCDB = 0x106;
};
}
@@ -0,0 +1,41 @@
namespace CoatiSoftware.CoatiPlugin.SolutionParser
{
public class CommandObject
{
private string _file = "";
private string _directory = "";
private string _command = "";
public string File
{
get { return _file; }
set { _file = value; }
}
public string Directory
{
get { return _directory; }
set { _directory = value; }
}
public string Command
{
get { return _command; }
set { _command = value; }
}
public string SerializeJSON()
{
string result = "\t{\n";
result += "\t\t\"directory\": \"" + _directory + "\",\n";
result += "\t\t\"command\": \"" + _command + "\",\n";
result += "\t\t\"file\": \"" + _file + "\"\n";
result += "\t}";
return result;
}
}
}
@@ -0,0 +1,28 @@
using System.Collections.Generic;
namespace CoatiSoftware.CoatiPlugin.SolutionParser
{
public class CompilationDatabase
{
private List<CommandObject> _commandObjects = new List<CommandObject>();
public void AddCommandObject(CommandObject commandObject)
{
_commandObjects.Add(commandObject);
}
public string SerializeJSON()
{
string result = "[\n";
foreach(CommandObject cm in _commandObjects)
{
result += cm.SerializeJSON() + ",";
}
result += "\n]";
return result;
}
}
}
@@ -0,0 +1,502 @@
using System;
using System.Collections.Generic;
using System.Linq;
using EnvDTE;
using Microsoft.VisualStudio.VCProjectEngine;
using System.Collections;
using System.IO;
using System.Diagnostics;
namespace CoatiSoftware.CoatiPlugin.SolutionParser
{
class SolutionParser
{
static private List<Guid> _reloadedProjectGuids = new List<Guid>();
static private List<string> _compatibilityFlags = new List<string>() { "-fms-extensions", "-fms-compatibility" };
static private string _compatibilityVersionFlagBase = "-fms-compatibility-version="; // I want to get the exact version at runtime for this flag, therefore I keep it seperate from the others to make things a bit easier...
static private string _compatibilityVersionFlag = _compatibilityVersionFlagBase + "19"; // This default version would correspond to VS2015
static public List<string> _additionalCompileFlags = new List<string>();
// 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;
}
public static List<CommandObject> CreateCommandObjects(Project project, string configurationName, string platformName, string cStandard)
{
List<CommandObject> result = new List<CommandObject>();
DTE dte = project.DTE;
Guid projectGuid = Utility.SolutionUtility.ReloadProject(project);
string version = dte.Version;
VCProject vcProject = project.Object as VCProject;
if (vcProject == null)
{
return result;
}
SetCompatibilityVersionFlag(vcProject, configurationName, platformName);
// gather include paths and preprocessor definitions of the project
List<string> includeDirectories = new List<string>();
List<string> preprocessorDefinitions = new List<string>();
Tuple<List<string>, List<string>> pathsAndFlags = GetProjectIncludeDirectoriesAndPreprocessorDefs(vcProject, configurationName, platformName);
includeDirectories = pathsAndFlags.Item1;
preprocessorDefinitions = pathsAndFlags.Item2;
// create command objects for all applicable project items
List<ProjectItem> projectItems = Utility.ProjectUtility.GetProjectItems(project);
VCConfiguration vcProjectConfig = GetProjectConfiguration(vcProject, configurationName, platformName);
string cppStandard = GetCppStandardString(vcProjectConfig);
foreach (EnvDTE.ProjectItem item in projectItems)
{
CommandObject cmdObj = CreateCommandObject(item, includeDirectories, preprocessorDefinitions, cppStandard, cStandard);
if (cmdObj != null)
{
result.Add(cmdObj);
}
}
if(projectGuid != Guid.Empty)
{
Utility.SolutionUtility.UnloadProject(projectGuid, dte);
}
return result;
}
static private Tuple<List<string>, List<string>> GetProjectIncludeDirectoriesAndPreprocessorDefs(VCProject project, string configurationName, string platformName)
{
List<string> includeDirectories = new List<string>();
List<string> preprocessorDefinitions = new List<string>();
IEnumerable configurations = project.Configurations as IEnumerable;
VCConfiguration vcProjectConfig = GetProjectConfiguration(project, configurationName, platformName);
if (vcProjectConfig != null)
{
// get additional include directories
// source: http://www.mztools.com/articles/2014/MZ2014005.aspx
IEnumerable projectTools = vcProjectConfig.Tools as IEnumerable;
foreach (Object tool in projectTools)
{
VCCLCompilerTool compilerTool = tool as VCCLCompilerTool;
if (compilerTool != null)
{
string additionalIncludeDirs = compilerTool.FullIncludePath;
string preprocessorDefinition = compilerTool.PreprocessorDefinitions;
string[] prepDefs = preprocessorDefinition.Split(';');
foreach (string prepDef in prepDefs)
{
preprocessorDefinitions.Add(prepDef);
}
string[] directories = additionalIncludeDirs.Split(';');
foreach (string directory in directories)
{
if (directory.Length <= 0)
{
continue;
}
includeDirectories.Add(directory);
}
break; // TODO: find some documentation on why the break is needed
// Apparently only the first 'tool' is needed, but why?
}
}
VCPlatform platform = vcProjectConfig.Platform as VCPlatform;
string platformIncludeDirectories = platform.IncludeDirectories;
string[] seperatedDirectories = platformIncludeDirectories.Split(';');
foreach (string directory in seperatedDirectories)
{
string resolvedDirectory = ResolveVSMacro(vcProjectConfig, directory);
string[] splitResolvedDirectory = resolvedDirectory.Split(';'); // resolved macros might result in concatenated paths
foreach (string p in splitResolvedDirectory)
{
includeDirectories.Add(p);
}
}
}
includeDirectories = includeDirectories.Distinct().ToList();
preprocessorDefinitions = preprocessorDefinitions.Distinct().ToList();
for (int i = 0; i < includeDirectories.Count; i++)
{
string path = includeDirectories.ElementAt(i).Replace("\\", "/"); // backslashes would cause some string-escaping hassles...
bool exists = true;
if (System.IO.Directory.Exists(path) == false)
{
exists = false;
}
// could be a relative path...
if(exists == false)
{
if (System.IO.Directory.Exists(project.ProjectDirectory + path) == false)
{
exists = false;
}
else
{
path = project.ProjectDirectory + path;
path = path.Replace("\\", "/");
exists = true;
}
}
if(exists == false)
{
includeDirectories.RemoveAt(i);
i--;
}
else
{
includeDirectories[i] = path;
}
}
return new Tuple<List<string>, List<string>>(includeDirectories, preprocessorDefinitions);
}
static private VCConfiguration GetProjectConfiguration(VCProject project, string configurationName, string platformName)
{
if(project == null)
{
return null;
}
IEnumerable configurations = project.Configurations as IEnumerable;
foreach (Object configuration in configurations)
{
VCConfiguration vcProjectConfig = configuration as VCConfiguration;
if (vcProjectConfig != null &&
vcProjectConfig.ConfigurationName == configurationName &&
vcProjectConfig.Platform.Name == platformName)
{
return vcProjectConfig;
}
}
return null;
}
static private CommandObject CreateCommandObject(EnvDTE.ProjectItem item, List<string> includeDirectories, List<string> preprocessorDefinitions, string vcStandard, string cStandard)
{
DTE dte = item.DTE;
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
{
CommandObject commandObject = new CommandObject();
commandObject.File = item.Name;
// only write source files to cdb, headers are implicit
if (CheckIsHeader(item))
{
return null;
}
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)")
{
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;
}
return null;
}
static private bool CheckIsHeader(EnvDTE.ProjectItem item)
{
Properties props = item.Properties;
string propString = "";
foreach (Property prop in props)
{
string propName = prop.Name;
string propValue = prop.Value as String;
propString += propName + " - " + propValue + "; ";
if (propName == "ItemType")
{
if (propValue as String == "ClInclude")
{
return true;
}
}
}
return false;
}
static private string ResolveVSMacro(VCConfiguration vcProjectConfig, string path)
{
string result = path;
Tuple<int, int> potentialMacroPosition = Utility.StringUtility.FindFirstRange(path, "$(", ")");
if (potentialMacroPosition != null)
{
string potentialMacro = path.Substring(potentialMacroPosition.Item1, potentialMacroPosition.Item2 - potentialMacroPosition.Item1 + 1);
string resolvedMacro = vcProjectConfig.Evaluate(potentialMacro);
result = path.Substring(0, potentialMacroPosition.Item1) + resolvedMacro + path.Substring(potentialMacroPosition.Item2 + 1);
}
return result;
}
static private void ReloadAll(DTE dte)
{
if (dte == null)
{
return;
}
EnvDTE.Solution solution = dte.Solution;
EnvDTE.Projects projects = solution.Projects;
foreach (EnvDTE.Project project in projects)
{
_reloadedProjectGuids.Add(Utility.SolutionUtility.ReloadProject(project));
}
}
static private void UnloadReloadedProjects(DTE dte)
{
foreach(Guid guid in _reloadedProjectGuids)
{
Utility.SolutionUtility.UnloadProject(guid, dte);
}
}
static private void SetCompatibilityVersionFlag(VCProject project, string configurationName, string platformName)
{
VCConfiguration vcProjectConfig = GetProjectConfiguration(project, configurationName, platformName);
if (vcProjectConfig != null)
{
IEnumerable projectTools = vcProjectConfig.Tools as IEnumerable;
foreach (Object tool in projectTools)
{
VCCLCompilerTool compilerTool = tool as VCCLCompilerTool;
if (compilerTool != null)
{
int majorCompilerVersion = GetCLMajorVersion(compilerTool, vcProjectConfig);
if (majorCompilerVersion > -1)
{
_compatibilityVersionFlag = _compatibilityVersionFlagBase + majorCompilerVersion.ToString();
return;
}
}
}
}
}
static private int GetCLMajorVersion(VCCLCompilerTool compilerTool, VCConfiguration vcProjectConfig)
{
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)
{
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;
foreach(string fd in finalDirectories)
{
string path = fd + "\\" + toolPath;
if(File.Exists(path))
{
FileVersionInfo info = FileVersionInfo.GetVersionInfo(path);
int version = info.FileMajorPart;
return version;
}
}
return -1;
}
// AFAIK there is no way to programmatically get the c++ standard version supported by any given VS version
// instead I'm refearing to the VS docu for that information
// https://msdn.microsoft.com/en-us/library/hh567368.aspx
static private string GetCppStandardString(VCConfiguration vcProjectConfig)
{
if(vcProjectConfig == null)
{
return "";
}
string result = "";
IVCRulePropertyStorage rules = vcProjectConfig.Rules.Item("ConfigurationGeneral");
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)
{
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";
}
}
return result;
}
}
}
@@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
namespace CoatiSoftware.CoatiPlugin
{
class SolutionUtility
{
public static String GetSolutionPath(DTE dte)
{
EnvDTE.Solution solution = dte.Solution;
return solution.FullName;
}
public static List<String> GetSolutionProjects(DTE dte)
{
List<String> projectNames = new List<String>();
EnvDTE.Solution solution = dte.Solution;
EnvDTE.Projects projects = solution.Projects;
foreach (EnvDTE.Project project in projects)
{
projectNames.Add(project.Name);
}
return projectNames;
}
public static List<String> GetSolutionProjectsFullNames(DTE dte)
{
List<String> projectNames = new List<String>();
EnvDTE.Solution solution = dte.Solution;
EnvDTE.Projects projects = solution.Projects;
foreach (EnvDTE.Project project in projects)
{
projectNames.Add(project.FullName);
}
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;
foreach (EnvDTE.Project project in projects)
{
if (project.CodeModel != null)
{
string language = project.CodeModel.Language;
languages.Add(language);
}
}
languages = languages.Distinct().ToList();
return languages;
}
public static bool GetSolutionIsSaved(DTE dte)
{
EnvDTE.Solution solution = dte.Solution;
return solution.Saved;
}
}
}
@@ -1,11 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EnvDTE;
namespace CoatiSoftware.CoatiPlugin
namespace CoatiSoftware.CoatiPlugin.Utility
{
class FileUtility
{
@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace CoatiSoftware.CoatiPlugin
namespace CoatiSoftware.CoatiPlugin.Utility
{
public class StateObject
{
@@ -0,0 +1,61 @@
using EnvDTE;
using System.Collections;
using System.Collections.Generic;
namespace CoatiSoftware.CoatiPlugin.Utility
{
public class ProjectUtility
{
public static bool ContainsCFiles(Project project)
{
List<ProjectItem> projectItems = GetProjectItems(project);
foreach (EnvDTE.ProjectItem item in projectItems)
{
if (item.FileCodeModel != null && item.FileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageVC)
{
string extension = item.Properties.Item("Extension").Value.ToString();
if (extension == ".c")
{
return true;
}
}
}
return false;
}
static public List<ProjectItem> GetProjectItems(Project project)
{
List<ProjectItem> items = new List<ProjectItem>();
IEnumerator itemEnumerator = project.ProjectItems.GetEnumerator();
while (itemEnumerator.MoveNext())
{
ProjectItem currentItem = (ProjectItem)itemEnumerator.Current;
items.Add(GetProjectItemsRecursive(currentItem, ref items));
}
return items;
}
static private ProjectItem GetProjectItemsRecursive(ProjectItem item, ref List<ProjectItem> projectItems)
{
if (item.ProjectItems == null)
{
return item;
}
IEnumerator items = item.ProjectItems.GetEnumerator();
while (items.MoveNext())
{
ProjectItem currentItem = (ProjectItem)items.Current;
projectItems.Add(GetProjectItemsRecursive(currentItem, ref projectItems));
}
return item;
}
}
}
@@ -0,0 +1,433 @@
using System;
using System.Collections.Generic;
using System.Linq;
using EnvDTE;
using EnvDTE80;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio;
namespace CoatiSoftware.CoatiPlugin.Utility
{
public class SolutionUtility
{
[DllImport("ole32.dll")]
private static extern void CreateBindCtx(int reserved, out IBindCtx bindCtx);
[DllImport("ole32.dll")]
private static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable runningObjectTable);
public class SolutionStructure
{
public class Node
{
public enum NodeType
{
UNKNOWN = 0,
PROJECT,
FOLDER
};
public string Name = "";
public Project Project = null;
public Object Foo = null;
public virtual NodeType GetNodeType() { throw (new NotImplementedException()); }
}
public class FolderNode : Node
{
public List<Node> SubNodes = new List<Node>();
public override NodeType GetNodeType() { return NodeType.FOLDER; }
}
public class ProjectNode : Node
{
public bool Include = false;
public override NodeType GetNodeType() { return NodeType.PROJECT; }
}
public List<Node> Nodes = new List<Node>();
}
public static String GetSolutionPath(DTE dte)
{
EnvDTE.Solution solution = dte.Solution;
return solution.FullName;
}
public static SolutionStructure GetSolutionVCProjects(DTE dte)
{
return GetProjectStructureRecursive(dte); ;
}
public static SolutionStructure GetProjectStructureRecursive(DTE dte)
{
EnvDTE.Solution solution = dte.Solution;
EnvDTE.Projects solutionProjects = solution.Projects;
List<Guid> guids = new List<Guid>();
SolutionStructure projectStructure = new SolutionStructure();
foreach(Project project in solutionProjects)
{
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);
projectStructure.Nodes.Add(folderNode);
}
}
return projectStructure;
}
private static SolutionStructure.Node GetSubProjects(EnvDTE.Project project)
{
ProjectItems projectItems = project.ProjectItems;
List<Project> items = new List<Project>();
foreach (ProjectItem item in projectItems)
{
Project p = item.Object as Project;
if(p != null)
{
items.Add(p);
}
}
if(items.Count > 0)
{
SolutionStructure.FolderNode folderNode = new SolutionStructure.FolderNode();
folderNode.Name = project.Name;
for (int i = 0; i < items.Count; i++)
{
Project item = items[i];
SolutionStructure.Node subFolderNode = GetSubProjects(item);
folderNode.SubNodes.Add(subFolderNode);
}
return folderNode;
}
else
{
SolutionStructure.ProjectNode projectNode = new SolutionStructure.ProjectNode();
projectNode.Name = project.Name;
projectNode.Project = project;
projectNode.Include = false;
return projectNode;
}
}
public static List<String> GetSolutionProjectsFullNames(DTE dte)
{
List<String> projectNames = new List<String>();
EnvDTE.Solution solution = dte.Solution;
EnvDTE.Projects projects = solution.Projects;
List<Guid> guids = new List<Guid>();
foreach (EnvDTE.Project project in projects)
{
guids.Add(ReloadProject(project));
}
projects = solution.Projects;
foreach (EnvDTE.Project project in projects)
{
projectNames.Add(project.FullName);
}
foreach (Guid guid in guids)
{
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;
foreach (EnvDTE.Project project in projects)
{
if (project.CodeModel != null)
{
string language = project.CodeModel.Language;
languages.Add(language);
}
}
languages = languages.Distinct().ToList();
return languages;
}
public static bool GetSolutionIsSaved(DTE dte)
{
EnvDTE.Solution solution = dte.Solution;
return solution.Saved;
}
public static List<List<string>> GetConfigurationAndPlatformNames(DTE dte)
{
List<List<string>> result = new List<List<string>>();
List<string> configNames = new List<string>();
List<string> platformNames = new List<string>();
DTE2 dte2 = SolutionUtility.GetDTE2(dte);
if(dte2 == null)
{
return result;
}
EnvDTE80.Solution2 solution = (EnvDTE80.Solution2)dte2.Solution;
if(solution == null)
{
return result;
}
EnvDTE80.SolutionBuild2 solutionBuild = (EnvDTE80.SolutionBuild2)solution.SolutionBuild;
if(solutionBuild == null)
{
return result;
}
foreach (SolutionConfiguration2 solutionConfiguration in solutionBuild.SolutionConfigurations)
{
foreach (SolutionContext context in solutionConfiguration.SolutionContexts)
{
string configurationName = context.ConfigurationName;
configNames.Add(configurationName);
string platformName = context.PlatformName;
platformNames.Add(platformName);
}
}
configNames = configNames.Distinct().ToList();
platformNames = platformNames.Distinct().ToList();
result.Add(configNames);
result.Add(platformNames);
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)
{
IBindCtx bindCtx = null;
CreateBindCtx(0, out bindCtx);
string displayName = "";
moniker[0].GetDisplayName(bindCtx, null, out displayName);
// add all VisualStudio ROT entries to list
if (displayName.StartsWith("!VisualStudio"))
{
object comObject;
runningObjectTable.GetObject(moniker[0], out comObject);
dte2List.Add((DTE2)comObject);
}
}
// find the correct dte2 instance (each running VS instance has one...)
KeyValuePair<DTE2, int> maxMatch = new KeyValuePair<DTE2, int>(null, 0);
foreach(DTE2 dte2 in dte2List)
{
int m = StringUtility.GetMatchingCharsFromStart(dte.Solution.FullName, dte2.Solution.FullName);
if(m > maxMatch.Value)
{
maxMatch = new KeyValuePair<DTE2, int>(dte2, m);
}
}
return maxMatch.Key;
}
// 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)
{
(vsSolution as IVsSolution4).ReloadProject(projectGuid);
return projectGuid;
}
}
}
return Guid.Empty;
}
static public void UnloadProject(Guid guid, DTE dte)
{
if (dte == null)
{
return;
}
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)
{
List<Project> projects = GetSolutionProjectList(dte); // dte.Solution.Projects;
foreach (Project project in projects)
{
if(ProjectUtility.ContainsCFiles(project) == true)
{
return true;
}
}
return false;
}
static public List<EnvDTE.Project> GetSolutionProjectList(DTE dte)
{
List<EnvDTE.Project> solutionProjects = new List<EnvDTE.Project>();
SolutionStructure solutionStructure = GetProjectStructureRecursive(dte);
Stack<SolutionStructure.Node> nodeStack = new Stack<Utility.SolutionUtility.SolutionStructure.Node>();
foreach (SolutionStructure.Node node in solutionStructure.Nodes)
{
nodeStack.Push(node);
}
while (nodeStack.Count > 0)
{
Utility.SolutionUtility.SolutionStructure.Node node = nodeStack.Pop();
string name = node.Name;
if (node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
{
solutionProjects.Add(node.Project);
}
else if (node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
{
Utility.SolutionUtility.SolutionStructure.FolderNode folderNode = node as Utility.SolutionUtility.SolutionStructure.FolderNode;
foreach (Utility.SolutionUtility.SolutionStructure.Node subNode in folderNode.SubNodes)
{
nodeStack.Push(subNode);
}
}
}
return solutionProjects;
}
}
}
@@ -0,0 +1,61 @@
using System;
namespace CoatiSoftware.CoatiPlugin.Utility
{
class StringUtility
{
static public Tuple<int, int> FindFirstRange(string text, string startTag, string endTag)
{
if(startTag.Length > 0 && endTag.Length > 0 && (startTag.Length + endTag.Length) < text.Length)
{
int start = text.IndexOf(startTag);
int end = text.IndexOf(endTag);
// just check wheter both, start and end, are valid and the end tag occurs after the start tag
if(start > -1 && end > -1 && end > start)
{
return new Tuple<int, int>(start, end);
}
}
return null;
}
static public int GetMatchingCharsFromStart(string a, string b)
{
int matchingChars = 0;
if (a != string.Empty)
{
a = a.ToLower();
}
else
{
return matchingChars;
}
if (b != string.Empty)
{
b = b.ToLower();
}
else
{
return matchingChars;
}
for (int i = 0; i < Math.Min(a.Length, b.Length); i++)
{
if (!char.Equals(a[i], b[i]))
{
break;
}
else
{
matchingChars++;
}
}
return matchingChars;
}
}
}
@@ -1,10 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CoatiSoftware.CoatiPlugin
namespace CoatiSoftware.CoatiPlugin.Utility
{
class SystemUtility
{
@@ -0,0 +1,277 @@
namespace CoatiSoftware.CoatiPlugin.Wizard
{
partial class ProjectSetupWindow
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProjectSetupWindow));
this.buttonCancel = new System.Windows.Forms.Button();
this.buttonCreate = new System.Windows.Forms.Button();
this.comboBoxConfiguration = new System.Windows.Forms.ComboBox();
this.comboBoxPlatform = new System.Windows.Forms.ComboBox();
this.labelConfiguration = new System.Windows.Forms.Label();
this.labelPlatform = new System.Windows.Forms.Label();
this.buttonSelectAll = new System.Windows.Forms.Button();
this.labelSelectProject = new System.Windows.Forms.Label();
this.folderBrowserTargetDirectory = new System.Windows.Forms.FolderBrowserDialog();
this.textBoxTargetDirectory = new System.Windows.Forms.TextBox();
this.buttonSelect = new System.Windows.Forms.Button();
this.textBoxFileName = new System.Windows.Forms.TextBox();
this.labelFileName = new System.Windows.Forms.Label();
this.labelFileNameEnding = new System.Windows.Forms.Label();
this.helpProvider1 = new System.Windows.Forms.HelpProvider();
this.comboBoxCStandard = new System.Windows.Forms.ComboBox();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.labelCStandard = new System.Windows.Forms.Label();
this.treeViewProjects = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// buttonCancel
//
this.helpProvider1.SetHelpString(this.buttonCancel, "Abort creation of the CDB");
this.buttonCancel.Location = new System.Drawing.Point(12, 413);
this.buttonCancel.Name = "buttonCancel";
this.helpProvider1.SetShowHelp(this.buttonCancel, true);
this.buttonCancel.Size = new System.Drawing.Size(92, 23);
this.buttonCancel.TabIndex = 9;
this.buttonCancel.Text = "Cancel";
this.toolTip1.SetToolTip(this.buttonCancel, "Abort creation of the CDB");
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// buttonCreate
//
this.helpProvider1.SetHelpString(this.buttonCreate, "Start creation of the CDB");
this.buttonCreate.Location = new System.Drawing.Point(178, 413);
this.buttonCreate.Name = "buttonCreate";
this.helpProvider1.SetShowHelp(this.buttonCreate, true);
this.buttonCreate.Size = new System.Drawing.Size(92, 23);
this.buttonCreate.TabIndex = 8;
this.buttonCreate.Text = "Create";
this.toolTip1.SetToolTip(this.buttonCreate, "Start creation of the CDB");
this.buttonCreate.UseVisualStyleBackColor = true;
this.buttonCreate.Click += new System.EventHandler(this.buttonCreate_Click);
//
// comboBoxConfiguration
//
this.comboBoxConfiguration.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxConfiguration.FormattingEnabled = true;
this.helpProvider1.SetHelpKeyword(this.comboBoxConfiguration, "Build configuration for CDB");
this.helpProvider1.SetHelpString(this.comboBoxConfiguration, "The selected build configuration determines the compile flags for the CDB");
this.comboBoxConfiguration.Location = new System.Drawing.Point(87, 277);
this.comboBoxConfiguration.Name = "comboBoxConfiguration";
this.helpProvider1.SetShowHelp(this.comboBoxConfiguration, true);
this.comboBoxConfiguration.Size = new System.Drawing.Size(183, 21);
this.comboBoxConfiguration.TabIndex = 3;
this.toolTip1.SetToolTip(this.comboBoxConfiguration, "The selected build configuration determines the compile flags for the CDB");
//
// comboBoxPlatform
//
this.comboBoxPlatform.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxPlatform.FormattingEnabled = true;
this.helpProvider1.SetHelpString(this.comboBoxPlatform, "The target platform determines some compiler flags included in the CDB");
this.comboBoxPlatform.Location = new System.Drawing.Point(87, 304);
this.comboBoxPlatform.Name = "comboBoxPlatform";
this.helpProvider1.SetShowHelp(this.comboBoxPlatform, true);
this.comboBoxPlatform.Size = new System.Drawing.Size(183, 21);
this.comboBoxPlatform.TabIndex = 4;
this.toolTip1.SetToolTip(this.comboBoxPlatform, "The target platform determines some compiler flags included in the CDB");
//
// labelConfiguration
//
this.labelConfiguration.AutoSize = true;
this.labelConfiguration.Location = new System.Drawing.Point(12, 280);
this.labelConfiguration.Name = "labelConfiguration";
this.labelConfiguration.Size = new System.Drawing.Size(69, 13);
this.labelConfiguration.TabIndex = 6;
this.labelConfiguration.Text = "Configuration";
//
// labelPlatform
//
this.labelPlatform.AutoSize = true;
this.labelPlatform.Location = new System.Drawing.Point(12, 307);
this.labelPlatform.Name = "labelPlatform";
this.labelPlatform.Size = new System.Drawing.Size(45, 13);
this.labelPlatform.TabIndex = 7;
this.labelPlatform.Text = "Platform";
//
// buttonSelectAll
//
this.helpProvider1.SetHelpString(this.buttonSelectAll, "Select all projects if not all are ticked. Deselect all otherwise");
this.buttonSelectAll.Location = new System.Drawing.Point(178, 248);
this.buttonSelectAll.Name = "buttonSelectAll";
this.helpProvider1.SetShowHelp(this.buttonSelectAll, true);
this.buttonSelectAll.Size = new System.Drawing.Size(92, 23);
this.buttonSelectAll.TabIndex = 2;
this.buttonSelectAll.Text = "De/Select All";
this.toolTip1.SetToolTip(this.buttonSelectAll, "Select all projects if not all are ticked. Deselect all otherwise");
this.buttonSelectAll.UseVisualStyleBackColor = true;
this.buttonSelectAll.Click += new System.EventHandler(this.buttonSelectAll_Click);
//
// labelSelectProject
//
this.labelSelectProject.AutoSize = true;
this.labelSelectProject.Location = new System.Drawing.Point(9, 9);
this.labelSelectProject.Name = "labelSelectProject";
this.labelSelectProject.Size = new System.Drawing.Size(78, 13);
this.labelSelectProject.TabIndex = 9;
this.labelSelectProject.Text = "Select Projects";
this.labelSelectProject.Click += new System.EventHandler(this.label1_Click);
//
// textBoxTargetDirectory
//
this.helpProvider1.SetHelpString(this.textBoxTargetDirectory, "Target directory where the CDB will be stored");
this.textBoxTargetDirectory.Location = new System.Drawing.Point(12, 333);
this.textBoxTargetDirectory.Name = "textBoxTargetDirectory";
this.helpProvider1.SetShowHelp(this.textBoxTargetDirectory, true);
this.textBoxTargetDirectory.Size = new System.Drawing.Size(177, 20);
this.textBoxTargetDirectory.TabIndex = 10;
this.toolTip1.SetToolTip(this.textBoxTargetDirectory, "Target directory where the CDB will be stored");
//
// buttonSelect
//
this.helpProvider1.SetHelpString(this.buttonSelect, "Pick a target directory via folder browser");
this.buttonSelect.Location = new System.Drawing.Point(195, 331);
this.buttonSelect.Name = "buttonSelect";
this.helpProvider1.SetShowHelp(this.buttonSelect, true);
this.buttonSelect.Size = new System.Drawing.Size(75, 23);
this.buttonSelect.TabIndex = 5;
this.buttonSelect.Text = "Browse";
this.toolTip1.SetToolTip(this.buttonSelect, "Pick a target directory via folder browser");
this.buttonSelect.UseVisualStyleBackColor = true;
this.buttonSelect.Click += new System.EventHandler(this.buttonSelect_Click);
//
// textBoxFileName
//
this.textBoxFileName.Location = new System.Drawing.Point(87, 360);
this.textBoxFileName.Name = "textBoxFileName";
this.textBoxFileName.Size = new System.Drawing.Size(148, 20);
this.textBoxFileName.TabIndex = 6;
this.textBoxFileName.TextChanged += new System.EventHandler(this.textBoxFileName_TextChanged);
this.textBoxFileName.Leave += new System.EventHandler(this.textBoxFileName_Leave);
//
// labelFileName
//
this.labelFileName.AutoSize = true;
this.labelFileName.Location = new System.Drawing.Point(12, 363);
this.labelFileName.Name = "labelFileName";
this.labelFileName.Size = new System.Drawing.Size(60, 13);
this.labelFileName.TabIndex = 13;
this.labelFileName.Text = "CDB Name";
//
// labelFileNameEnding
//
this.labelFileNameEnding.AutoSize = true;
this.labelFileNameEnding.Location = new System.Drawing.Point(241, 363);
this.labelFileNameEnding.Name = "labelFileNameEnding";
this.labelFileNameEnding.Size = new System.Drawing.Size(29, 13);
this.labelFileNameEnding.TabIndex = 14;
this.labelFileNameEnding.Text = ".json";
//
// comboBoxCStandard
//
this.comboBoxCStandard.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboBoxCStandard.FormattingEnabled = true;
this.helpProvider1.SetHelpString(this.comboBoxCStandard, "Your Solution contains C Files. Please specify which C standard is to be used for" +
" building.");
this.comboBoxCStandard.Location = new System.Drawing.Point(87, 386);
this.comboBoxCStandard.Name = "comboBoxCStandard";
this.helpProvider1.SetShowHelp(this.comboBoxCStandard, true);
this.comboBoxCStandard.Size = new System.Drawing.Size(183, 21);
this.comboBoxCStandard.TabIndex = 7;
this.toolTip1.SetToolTip(this.comboBoxCStandard, "Your Solution contains C Files. Please specify which C standard is to be used for" +
" building.");
//
// labelCStandard
//
this.labelCStandard.AutoSize = true;
this.labelCStandard.Location = new System.Drawing.Point(12, 389);
this.labelCStandard.Name = "labelCStandard";
this.labelCStandard.Size = new System.Drawing.Size(60, 13);
this.labelCStandard.TabIndex = 16;
this.labelCStandard.Text = "C Standard";
//
// treeViewProjects
//
this.treeViewProjects.CheckBoxes = true;
this.treeViewProjects.Location = new System.Drawing.Point(12, 26);
this.treeViewProjects.Name = "treeViewProjects";
this.treeViewProjects.Size = new System.Drawing.Size(258, 216);
this.treeViewProjects.TabIndex = 17;
this.treeViewProjects.MouseUp += new System.Windows.Forms.MouseEventHandler(this.ProjectCheckList_MouseUp);
this.treeViewProjects.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeViewProjects_NodeCheckChanged);
//
// ProjectSetupWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoSize = true;
this.ClientSize = new System.Drawing.Size(282, 443);
this.Controls.Add(this.treeViewProjects);
this.Controls.Add(this.labelCStandard);
this.Controls.Add(this.comboBoxCStandard);
this.Controls.Add(this.labelFileNameEnding);
this.Controls.Add(this.labelFileName);
this.Controls.Add(this.textBoxFileName);
this.Controls.Add(this.buttonSelect);
this.Controls.Add(this.textBoxTargetDirectory);
this.Controls.Add(this.labelSelectProject);
this.Controls.Add(this.buttonSelectAll);
this.Controls.Add(this.labelPlatform);
this.Controls.Add(this.labelConfiguration);
this.Controls.Add(this.comboBoxPlatform);
this.Controls.Add(this.comboBoxConfiguration);
this.Controls.Add(this.buttonCreate);
this.Controls.Add(this.buttonCancel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.helpProvider1.SetHelpString(this, "Create a CDB from the current C++ solution.");
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ProjectSetupWindow";
this.helpProvider1.SetShowHelp(this, true);
this.Text = "Create Compilation Database";
this.toolTip1.SetToolTip(this, "Create a CDB from the current C++ solution.");
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.Button buttonCreate;
private System.Windows.Forms.ComboBox comboBoxConfiguration;
private System.Windows.Forms.ComboBox comboBoxPlatform;
private System.Windows.Forms.Label labelConfiguration;
private System.Windows.Forms.Label labelPlatform;
private System.Windows.Forms.Button buttonSelectAll;
private System.Windows.Forms.Label labelSelectProject;
private System.Windows.Forms.FolderBrowserDialog folderBrowserTargetDirectory;
private System.Windows.Forms.TextBox textBoxTargetDirectory;
private System.Windows.Forms.Button buttonSelect;
private System.Windows.Forms.TextBox textBoxFileName;
private System.Windows.Forms.Label labelFileName;
private System.Windows.Forms.Label labelFileNameEnding;
private System.Windows.Forms.HelpProvider helpProvider1;
private System.Windows.Forms.ToolTip toolTip1;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
private System.Windows.Forms.ComboBox comboBoxCStandard;
private System.Windows.Forms.Label labelCStandard;
private System.Windows.Forms.TreeView treeViewProjects;
}
}
@@ -0,0 +1,432 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
namespace CoatiSoftware.CoatiPlugin.Wizard
{
public partial class ProjectSetupWindow : Form
{
public class SolutionProject
{
public string m_name = "";
public bool m_include = false;
public SolutionProject(string name, bool include)
{
m_name = name;
m_include = include;
}
}
public delegate void OnCreateProject(List<EnvDTE.Project> projects, string configurationName, string platformName, string targetDir, string fileName, string cStandard);
// public List<SolutionProject> m_projects = new List<SolutionProject>();
public Utility.SolutionUtility.SolutionStructure m_projectStructure = new Utility.SolutionUtility.SolutionStructure();
public List<string> m_configurations = new List<string>();
public List<string> m_platforms = new List<string>();
public OnCreateProject m_onCreateProject = null;
public string m_solutionDirectory = "";
public string m_solutionFileName = "foo";
public bool m_containsCFiles = false;
private List<string> m_cStandards = new List<string>() { "c1x", "gnu1x", "iso9899:201x", "c11", "gnu11", "iso9899:2011",
"c9x", "gnu9x", "iso9899:199x", "c99", "gnu99", "iso9899:1999", "iso9899:199409", "c90", "gnu90", "iso9899:1990",
"c89", "gnu89" };
public ProjectSetupWindow()
{
InitializeComponent();
UpdateGUI();
buttonCreate.Enabled = false;
}
public void UpdateGUI()
{
InitProjectCheckList();
InitComboBoxConfigurations();
InitComboBoxPlatforms();
InitTextBoxTargetDirectory();
InitTextBoxFileName();
InitComboBoxCStandard();
}
private void InitComboBoxConfigurations()
{
foreach(string configuration in m_configurations)
{
comboBoxConfiguration.Items.Add(configuration);
}
if(comboBoxConfiguration.Items.Count > 0)
{
comboBoxConfiguration.SelectedIndex = 0;
}
}
private void InitComboBoxPlatforms()
{
foreach(string platform in m_platforms)
{
comboBoxPlatform.Items.Add(platform);
}
if(comboBoxPlatform.Items.Count > 0)
{
comboBoxPlatform.SelectedIndex = 0;
}
}
private void InitProjectCheckList()
{
//foreach (SolutionProject project in m_projects)
//{
// treeViewProjects.Nodes.Add(new TreeNode(project.m_name));
//}
foreach(Utility.SolutionUtility.SolutionStructure.Node node in m_projectStructure.Nodes)
{
if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
{
TreeNode treeNode = new TreeNode(node.Name);
node.Foo = treeNode;
treeViewProjects.Nodes.Add(treeNode);
}
else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
{
TreeNode[] subNodes = GetSubNodes(node as Utility.SolutionUtility.SolutionStructure.FolderNode);
TreeNode treeNode = new TreeNode(node.Name, subNodes);
node.Foo = treeNode;
treeViewProjects.Nodes.Add(treeNode);
}
}
}
private TreeNode[] GetSubNodes(Utility.SolutionUtility.SolutionStructure.FolderNode folderNode)
{
List<TreeNode> result = new List<TreeNode>();
foreach(Utility.SolutionUtility.SolutionStructure.Node node in folderNode.SubNodes)
{
if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT)
{
TreeNode treeNode = new TreeNode(node.Name);
node.Foo = treeNode;
result.Add(treeNode);
}
else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
{
TreeNode[] subNodes = GetSubNodes(node as Utility.SolutionUtility.SolutionStructure.FolderNode);
TreeNode treeNode = new TreeNode(node.Name, subNodes);
node.Foo = treeNode;
result.Add(treeNode);
}
}
return result.ToArray();
}
private void InitTextBoxTargetDirectory()
{
folderBrowserTargetDirectory.SelectedPath = m_solutionDirectory;
string rootDirectory = folderBrowserTargetDirectory.SelectedPath.ToString();
textBoxTargetDirectory.Text = rootDirectory;
}
private void InitTextBoxFileName()
{
textBoxFileName.Text = m_solutionFileName;
// MakeFileNameUnique();
}
private void InitComboBoxCStandard()
{
if(m_containsCFiles == false)
{
comboBoxCStandard.Hide();
labelCStandard.Hide();
}
else
{
comboBoxCStandard.Show();
labelCStandard.Show();
foreach(string standard in m_cStandards)
{
comboBoxCStandard.Items.Add(standard);
}
comboBoxCStandard.SelectedIndex = 3;
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
Close();
}
private void buttonCreate_Click(object sender, EventArgs e)
{
OnCreate();
}
private void OnCreate()
{
if (m_onCreateProject != null)
{
string configurationName = "";
string platformName = "";
configurationName = comboBoxConfiguration.SelectedItem as string;
platformName = comboBoxPlatform.SelectedItem as string;
string targetDir = textBoxTargetDirectory.Text;
if(Directory.Exists(targetDir) && CheckFileNameIsValid(textBoxFileName.Text))
{
if (CheckFileExists())
{
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)
{
MakeFileNameUnique();
return;
}
}
string cStandard = "c11";
if(m_containsCFiles)
{
cStandard = comboBoxCStandard.SelectedItem as string;
}
m_onCreateProject(GetTreeViewProjectItems(), configurationName, platformName, targetDir, textBoxFileName.Text, cStandard);
Close();
}
else
{
if(Directory.Exists(targetDir) == false)
{
MessageBox.Show("The target directory does not exist.", "Coati Plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
if (CheckFileNameIsValid(textBoxFileName.Text) == false)
{
MessageBox.Show("The chosen file name is not valid.", "Coati Plugin", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
}
private bool CheckFileNameIsValid(string fileName)
{
Regex badChars = new Regex("[" + Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars())) + "]");
if(badChars.IsMatch(fileName))
{
return false;
}
return true;
}
private bool CheckFileExists()
{
string fileName = textBoxFileName.Text;
string path = textBoxTargetDirectory.Text;
string extension = labelFileNameEnding.Text;
return File.Exists(path + "\\" + fileName + extension);
}
private List<EnvDTE.Project> GetTreeViewProjectItems()
{
List<EnvDTE.Project> solutionProjects = new List<EnvDTE.Project>();
// Stack<TreeNode> treeNodes = new Stack<TreeNode>();
Stack<Utility.SolutionUtility.SolutionStructure.Node> nodeStack = new Stack<Utility.SolutionUtility.SolutionStructure.Node>();
foreach(Utility.SolutionUtility.SolutionStructure.Node node in m_projectStructure.Nodes)
{
nodeStack.Push(node);
}
while(nodeStack.Count > 0)
{
Utility.SolutionUtility.SolutionStructure.Node node = nodeStack.Pop();
bool include = (node.Foo as TreeNode).Checked;
string name = node.Name;
if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.PROJECT
&& (node.Foo as TreeNode).Checked == true)
{
solutionProjects.Add(node.Project);
}
else if(node.GetNodeType() == Utility.SolutionUtility.SolutionStructure.Node.NodeType.FOLDER)
{
Utility.SolutionUtility.SolutionStructure.FolderNode folderNode = node as Utility.SolutionUtility.SolutionStructure.FolderNode;
foreach(Utility.SolutionUtility.SolutionStructure.Node subNode in folderNode.SubNodes)
{
nodeStack.Push(subNode);
}
}
}
return solutionProjects;
}
private void ProjectCheckList_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void buttonSelectAll_Click(object sender, EventArgs e)
{
bool select = false;
// if one or more items are unselected, select all
// otherwise deselect all
for (int i = 0; i < treeViewProjects.Nodes.Count; i++)
{
if (treeViewProjects.Nodes[i].Checked == false)
{
select = true;
}
}
for (int i = 0; i < treeViewProjects.Nodes.Count; i++)
{
treeViewProjects.Nodes[i].Checked = select;
}
UpdateCreateButtonEnabled();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void buttonSelect_Click(object sender, EventArgs e)
{
if(Directory.Exists(textBoxTargetDirectory.Text))
{
folderBrowserTargetDirectory.SelectedPath = textBoxTargetDirectory.Text;
}
folderBrowserTargetDirectory.SelectedPath = textBoxTargetDirectory.Text;
DialogResult result = folderBrowserTargetDirectory.ShowDialog();
string selectedPath = folderBrowserTargetDirectory.SelectedPath;
textBoxTargetDirectory.Text = selectedPath;
}
private void treeViewProjects_NodeCheckChanged(object sender, TreeViewEventArgs e)
{
// treeViewProjects.AfterCheck -= treeViewProjects_NodeCheckChanged;
Stack<TreeNode> nodeStack = new Stack<TreeNode>();
foreach (TreeNode subNode in e.Node.Nodes)
{
nodeStack.Push(subNode);
}
while (nodeStack.Count > 0)
{
var node = nodeStack.Pop();
node.Checked = e.Node.Checked;
//foreach (TreeNode subNode in node.Nodes)
//{
// nodeStack.Push(subNode);
//}
}
// treeViewProjects.AfterCheck += treeViewProjects_NodeCheckChanged;
}
private void textBoxFileName_TextChanged(object sender, EventArgs e)
{
}
private void textBoxFileName_Leave(object sender, EventArgs e)
{
// MakeFileNameUnique();
}
private void MakeFileNameUnique()
{
string fileName = textBoxFileName.Text;
int i = 0;
while (CheckFileExists())
{
++i;
textBoxFileName.Text = fileName + i.ToString();
}
}
private void ProjectCheckList_ItemCheck(object sender, ItemCheckEventArgs e)
{
}
private void ProjectCheckList_Click(object sender, EventArgs e)
{
}
private void ProjectCheckList_MouseUp(object sender, MouseEventArgs e)
{
UpdateCreateButtonEnabled();
}
private void UpdateCreateButtonEnabled()
{
bool anythingChecked = false;
Stack<TreeNode> treeNodes = new Stack<TreeNode>();
foreach(TreeNode node in treeViewProjects.Nodes)
{
treeNodes.Push(node);
}
while(treeNodes.Count > 0)
{
TreeNode node = treeNodes.Pop();
if(node.Nodes.Count <= 0 && node.Checked == true)
{
anythingChecked = true;
}
foreach(TreeNode subNode in node.Nodes)
{
treeNodes.Push(subNode);
}
}
buttonCreate.Enabled = anythingChecked;
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,84 @@
namespace CoatiSoftware.CoatiPlugin.Wizard
{
partial class WindowCreateCDB
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WindowCreateCDB));
this.progressBar = new System.Windows.Forms.ProgressBar();
this.labelStatus = new System.Windows.Forms.Label();
this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
this.SuspendLayout();
//
// progressBar
//
this.progressBar.Location = new System.Drawing.Point(12, 12);
this.progressBar.Name = "progressBar";
this.progressBar.Size = new System.Drawing.Size(259, 23);
this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
this.progressBar.TabIndex = 0;
//
// labelStatus
//
this.labelStatus.AutoSize = true;
this.labelStatus.Location = new System.Drawing.Point(13, 42);
this.labelStatus.Name = "labelStatus";
this.labelStatus.Size = new System.Drawing.Size(52, 13);
this.labelStatus.TabIndex = 1;
this.labelStatus.Text = "Waiting...";
//
// backgroundWorker1
//
this.backgroundWorker1.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker1_DoWork);
this.backgroundWorker1.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker1_ProgressChanged);
this.backgroundWorker1.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker1_RunWorkerCompleted);
//
// WindowCreateCDB
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 63);
this.Controls.Add(this.labelStatus);
this.Controls.Add(this.progressBar);
this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "WindowCreateCDB";
this.Text = "Creating Compilation Data Base";
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.WindowCreateCDB_FormClosed);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ProgressBar progressBar;
private System.Windows.Forms.Label labelStatus;
private System.ComponentModel.BackgroundWorker backgroundWorker1;
}
}
@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CoatiSoftware.CoatiPlugin.Wizard
{
public partial class WindowCreateCDB : Form
{
public delegate void OnFinishedCreatingCDB(SolutionParser.CompilationDatabase cdb, string directory, string fileName);
private OnFinishedCreatingCDB m_onFinishedCreateCDB = null;
private List<EnvDTE.Project> m_projects = new List<EnvDTE.Project>();
string m_configurationName = "";
string m_platformName = "";
string m_targetDir = "";
string m_fileName = "";
string m_cStandard = "";
SolutionParser.CompilationDatabase m_cdb = null;
public OnFinishedCreatingCDB CallbackOnFinishedCreatingCDB
{
get { return m_onFinishedCreateCDB; }
set { m_onFinishedCreateCDB = value; }
}
public List<EnvDTE.Project> Projects
{
get { return m_projects; }
set { m_projects = value; }
}
public string ConfigurationName
{
get { return m_configurationName; }
set { m_configurationName = value; }
}
public string PlatformName
{
get { return m_platformName; }
set { m_platformName = value; }
}
public string TargetDir
{
get { return m_targetDir; }
set { m_targetDir = value; }
}
public string FileName
{
get { return m_fileName; }
set { m_fileName = value; }
}
public string CStandard
{
get { return m_cStandard; }
set { m_cStandard = value; }
}
public WindowCreateCDB()
{
InitializeComponent();
progressBar.Maximum = 100;
progressBar.Value = 0;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = true;
}
public void StartWorking()
{
// Show();
backgroundWorker1.RunWorkerAsync();
}
private SolutionParser.CompilationDatabase CreateCDB()
{
SolutionParser.CompilationDatabase cdb = new SolutionParser.CompilationDatabase();
int projectsProcessed = 0;
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;
backgroundWorker1.ReportProgress((int)(relativProgress * 100), "Processing project \"" + project.Name + "\"");
foreach (SolutionParser.CommandObject obj in commandObjects)
{
cdb.AddCommandObject(obj);
}
}
return cdb;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
m_cdb = CreateCDB();
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
labelStatus.Text = e.UserState as string;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if(e.Cancelled == false && e.Error == null)
{
if (m_onFinishedCreateCDB != null)
{
m_onFinishedCreateCDB(m_cdb, m_targetDir, m_fileName);
}
}
Close();
}
private void WindowCreateCDB_FormClosed(object sender, FormClosedEventArgs e)
{
backgroundWorker1.CancelAsync();
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,92 @@
namespace CoatiSoftware.CoatiPlugin.Wizard
{
partial class WindowMessage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WindowMessage));
this.buttonCancel = new System.Windows.Forms.Button();
this.buttonOK = new System.Windows.Forms.Button();
this.labelContent = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonCancel.Location = new System.Drawing.Point(13, 78);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 0;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// buttonOK
//
this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonOK.Location = new System.Drawing.Point(257, 78);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 1;
this.buttonOK.Text = "OK";
this.buttonOK.UseVisualStyleBackColor = true;
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
//
// labelContent
//
this.labelContent.AutoSize = true;
this.labelContent.Location = new System.Drawing.Point(13, 13);
this.labelContent.MaximumSize = new System.Drawing.Size(300, 0);
this.labelContent.Name = "labelContent";
this.labelContent.Size = new System.Drawing.Size(44, 13);
this.labelContent.TabIndex = 2;
this.labelContent.Text = "Content";
//
// WindowMessage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(344, 113);
this.Controls.Add(this.labelContent);
this.Controls.Add(this.buttonOK);
this.Controls.Add(this.buttonCancel);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "WindowMessage";
this.Text = "Message";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.Button buttonOK;
private System.Windows.Forms.Label labelContent;
}
}
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace CoatiSoftware.CoatiPlugin.Wizard
{
public partial class WindowMessage : Form
{
private string m_title = "Title";
private string m_message = "Message";
public delegate void Callback();
private Callback m_onOK = null;
private Callback m_onCancel = null;
public string Title
{
get { return m_title; }
set { m_title = value; }
}
public string Message
{
get { return m_message; }
set { m_message = value; }
}
public Callback OnOK
{
get { return m_onOK; }
set { m_onOK = value; }
}
public Callback OnCancel
{
get { return m_onCancel; }
set { m_onCancel = value; }
}
public WindowMessage()
{
InitializeComponent();
}
public void RefreshWindow()
{
Text = m_title;
labelContent.Text = m_message;
//if(m_onOK != null)
//{
// buttonOK.Show();
//}
//else
//{
// buttonOK.Hide();
//}
if(m_onCancel != null)
{
buttonCancel.Show();
}
else
{
buttonCancel.Hide();
}
}
private void buttonCancel_Click(object sender, EventArgs e)
{
if(m_onCancel != null)
{
m_onCancel();
}
Close();
}
private void buttonOK_Click(object sender, EventArgs e)
{
if(m_onOK != null)
{
m_onOK();
}
Close();
}
}
}
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 70 KiB

@@ -1,10 +1,11 @@
<?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.6" Language="en-US" Publisher="Coati Software OG" />
<Identity Id="acf15780-03b5-440e-a41e-db79b7043fc2" Version="0.8.12" 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>
<ReleaseNotes>Creation of CDBs is in beta and may change in future versions</ReleaseNotes>
<Icon>coati.ico</Icon>
</Metadata>
<Installation InstalledByMsi="false">