PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/vsaddin/src/Builder.cs

https://bitbucket.org/cleto/zeroc-ice-package
C# | 3605 lines | 3476 code | 79 blank | 50 comment | 117 complexity | 53895246aad3d943126a122f84da7a35 MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, GPL-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. // **********************************************************************
  2. //
  3. // Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
  4. //
  5. // This copy of Ice is licensed to you under the terms described in the
  6. // ICE_LICENSE file included in this distribution.
  7. //
  8. // **********************************************************************
  9. using System;
  10. using System.Text;
  11. using System.IO;
  12. using System.Diagnostics;
  13. using System.Collections.Generic;
  14. using Extensibility;
  15. using EnvDTE;
  16. using EnvDTE80;
  17. using Microsoft.VisualStudio;
  18. using Microsoft.VisualStudio.CommandBars;
  19. using Microsoft.VisualStudio.VCProjectEngine;
  20. using Microsoft.VisualStudio.Shell;
  21. using Microsoft.VisualStudio.Shell.Interop;
  22. using System.Resources;
  23. using System.Reflection;
  24. using VSLangProj;
  25. using System.Globalization;
  26. using Microsoft.VisualStudio.OLE.Interop;
  27. using System.Runtime.InteropServices;
  28. using System.Windows.Forms;
  29. using DependenciesMap = System.Collections.Generic.Dictionary<string,
  30. System.Collections.Generic.Dictionary<string,
  31. System.Collections.Generic.List<string>>>;
  32. namespace Ice.VisualStudio
  33. {
  34. //
  35. // This class is used to asynchronously read the output of a Slice compiler
  36. // process.
  37. //
  38. public class StreamReader
  39. {
  40. public void appendData(object sendingProcess, DataReceivedEventArgs outLine)
  41. {
  42. if(outLine.Data != null)
  43. {
  44. _data += outLine.Data + "\n";
  45. }
  46. }
  47. public string data()
  48. {
  49. return _data;
  50. }
  51. private string _data = "";
  52. }
  53. public class Builder : IDisposable, IVsTrackProjectDocumentsEvents2
  54. {
  55. protected virtual void Dispose(bool disposing)
  56. {
  57. if(disposing)
  58. {
  59. if(_serviceProvider != null)
  60. {
  61. _serviceProvider.Dispose();
  62. }
  63. if(_errorListProvider != null)
  64. {
  65. _errorListProvider.Dispose();
  66. }
  67. }
  68. }
  69. public void Dispose()
  70. {
  71. Dispose(true);
  72. GC.SuppressFinalize(this);
  73. }
  74. public DTE getCurrentDTE()
  75. {
  76. return _applicationObject.DTE;
  77. }
  78. public DTE2 getApplicationObject()
  79. {
  80. return _applicationObject;
  81. }
  82. public void init(DTE2 application, ext_ConnectMode connectMode, AddIn addInInstance)
  83. {
  84. _applicationObject = application;
  85. _addInInstance = addInInstance;
  86. _connectMode = connectMode;
  87. //
  88. // Subscribe to solution events.
  89. //
  90. if(_connectMode != ext_ConnectMode.ext_cm_CommandLine)
  91. {
  92. _solutionEvents = application.Events.SolutionEvents;
  93. _solutionEvents.Opened += new _dispSolutionEvents_OpenedEventHandler(solutionOpened);
  94. _solutionEvents.AfterClosing += new _dispSolutionEvents_AfterClosingEventHandler(afterClosing);
  95. _solutionEvents.ProjectAdded += new _dispSolutionEvents_ProjectAddedEventHandler(projectAdded);
  96. _solutionEvents.ProjectRemoved += new _dispSolutionEvents_ProjectRemovedEventHandler(projectRemoved);
  97. _solutionEvents.ProjectRenamed += new _dispSolutionEvents_ProjectRenamedEventHandler(projectRenamed);
  98. _selectionEvents = application.Events.SelectionEvents;
  99. _selectionEvents.OnChange += new _dispSelectionEvents_OnChangeEventHandler(selectionChange);
  100. }
  101. _buildEvents = _applicationObject.Events.BuildEvents;
  102. _buildEvents.OnBuildBegin += new _dispBuildEvents_OnBuildBeginEventHandler(buildBegin);
  103. _buildEvents.OnBuildDone += new _dispBuildEvents_OnBuildDoneEventHandler(buildDone);
  104. if(_connectMode != ext_ConnectMode.ext_cm_CommandLine)
  105. {
  106. beginTrackDocumentEvents();
  107. //
  108. // Ensure DEVPATH isn't empty, if there is a project in development mode and DEVPATH is
  109. // empty vshosting process will crash.
  110. //
  111. string devPath = Environment.GetEnvironmentVariable("DEVPATH");
  112. if(String.IsNullOrEmpty(devPath))
  113. {
  114. setDotNetDevPath(Util.getIceHome() + "\\bin\\");
  115. }
  116. //
  117. // Subscribe to command events.
  118. //
  119. foreach(Command c in _applicationObject.Commands)
  120. {
  121. if(c.Name.Equals("Project.AddNewItem"))
  122. {
  123. _addNewItemEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  124. _addNewItemEvent.AfterExecute +=
  125. new _dispCommandEvents_AfterExecuteEventHandler(afterAddNewItem);
  126. }
  127. else if(c.Name.Equals("Edit.Remove"))
  128. {
  129. _editRemoveEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  130. _editRemoveEvent.AfterExecute +=
  131. new _dispCommandEvents_AfterExecuteEventHandler(editDeleteEvent);
  132. }
  133. else if(c.Name.Equals("Edit.Delete"))
  134. {
  135. _editDeleteEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  136. _editDeleteEvent.AfterExecute +=
  137. new _dispCommandEvents_AfterExecuteEventHandler(editDeleteEvent);
  138. }
  139. else if(c.Name.Equals("Project.ExcludeFromProject"))
  140. {
  141. _excludeFromProjectEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  142. _excludeFromProjectEvent.BeforeExecute +=
  143. new _dispCommandEvents_BeforeExecuteEventHandler(beforeExcludeFromProjectEvent);
  144. _excludeFromProjectEvent.AfterExecute +=
  145. new _dispCommandEvents_AfterExecuteEventHandler(afterExcludeFromProjectEvent);
  146. }
  147. else if(c.Name.Equals("Project.AddExistingItem"))
  148. {
  149. _addExistingItemEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  150. _addExistingItemEvent.AfterExecute +=
  151. new _dispCommandEvents_AfterExecuteEventHandler(afterAddExistingItem);
  152. }
  153. else if(c.Name.Equals("Build.Cancel"))
  154. {
  155. _buildCancelEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  156. _buildCancelEvent.AfterExecute +=
  157. new _dispCommandEvents_AfterExecuteEventHandler(afterBuildCancel);
  158. }
  159. else if(c.Name.Equals("Debug.Start"))
  160. {
  161. _debugStartEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  162. _debugStartEvent.BeforeExecute +=
  163. new _dispCommandEvents_BeforeExecuteEventHandler(setDebugEnvironmentStartupProject);
  164. }
  165. else if(c.Name.Equals("Debug.StepInto"))
  166. {
  167. _debugStepIntoEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  168. _debugStepIntoEvent.BeforeExecute +=
  169. new _dispCommandEvents_BeforeExecuteEventHandler(setDebugEnvironmentStartupProject);
  170. }
  171. else if(c.Name.Equals("ClassViewContextMenus.ClassViewProject.Debug.StepIntonewinstance"))
  172. {
  173. _debugStepIntoNewInstance = application.Events.get_CommandEvents(c.Guid, c.ID);
  174. _debugStepIntoNewInstance.BeforeExecute +=
  175. new _dispCommandEvents_BeforeExecuteEventHandler(setDebugEnvironmentActiveProject);
  176. }
  177. else if (c.Name.Equals("Debug.StartWithoutDebugging"))
  178. {
  179. _debugStartWithoutDebuggingEvent = application.Events.get_CommandEvents(c.Guid, c.ID);
  180. _debugStartWithoutDebuggingEvent.BeforeExecute +=
  181. new _dispCommandEvents_BeforeExecuteEventHandler(setDebugEnvironmentStartupProject);
  182. }
  183. else if (c.Name.Equals("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance"))
  184. {
  185. _debugStartNewInstance = application.Events.get_CommandEvents(c.Guid, c.ID);
  186. _debugStartNewInstance.BeforeExecute +=
  187. new _dispCommandEvents_BeforeExecuteEventHandler(setDebugEnvironmentActiveProject);
  188. }
  189. else if (c.Guid.Equals(Util.refreshCommandGUID) && c.ID == Util.refreshCommandID)
  190. {
  191. Util.setRefreshCommand(c);
  192. }
  193. }
  194. }
  195. _serviceProvider =
  196. new ServiceProvider((Microsoft.VisualStudio.OLE.Interop.IServiceProvider)_applicationObject.DTE);
  197. initErrorListProvider();
  198. if(connectMode != ext_ConnectMode.ext_cm_CommandLine)
  199. {
  200. setupCommandBars();
  201. }
  202. }
  203. void selectionChange()
  204. {
  205. try
  206. {
  207. Project p = getActiveProject();
  208. if(p != null && Util.isSliceBuilderEnabled(p))
  209. {
  210. initializeProject(p);
  211. }
  212. }
  213. catch(Exception ex)
  214. {
  215. Util.unexpectedExceptionWarning(ex);
  216. throw;
  217. }
  218. }
  219. void initializeProject(Project p)
  220. {
  221. DependenciesMap dependenciesMap = getDependenciesMap();
  222. if(p != null && !dependenciesMap.ContainsKey(p.FullName))
  223. {
  224. if((Util.isCSharpProject(p) || Util.isCppProject(p)) && Util.isSliceBuilderEnabled(p))
  225. {
  226. Util.fix(p);
  227. Util.getCurrentDTE().StatusBar.Text = "Ice Add-in: checking/updating settings for project '" + p.FullName + "'";
  228. Util.verifyProjectSettings(p);
  229. Util.getCurrentDTE().StatusBar.Text = "Ice Add-in: loading project '" + p.FullName + "'";
  230. if(!Util.isVBProject(p))
  231. {
  232. dependenciesMap[p.FullName] = new Dictionary<string, List<string>>();
  233. buildProject(p, true, vsBuildScope.vsBuildScopeSolution, false);
  234. }
  235. }
  236. }
  237. if(hasErrors())
  238. {
  239. bringErrorsToFront();
  240. }
  241. }
  242. void editDeleteEvent(string Guid, int ID, object CustomIn, object CustomOut)
  243. {
  244. try
  245. {
  246. if(_deletedFile == null)
  247. {
  248. return;
  249. }
  250. Project project = getActiveProject();
  251. if(project == null)
  252. {
  253. return;
  254. }
  255. removeDependency(project, _deletedFile);
  256. _deletedFile = null;
  257. clearErrors(project);
  258. buildProject(project, false, vsBuildScope.vsBuildScopeProject, false);
  259. }
  260. catch(Exception ex)
  261. {
  262. Util.unexpectedExceptionWarning(ex);
  263. throw;
  264. }
  265. }
  266. //
  267. // In C# project type the delete event isn't triggered by exclude item command.
  268. // We use the before and after events of the command to remove generated items
  269. // when a slice file is excluded. C++ projects handle that as part of delete item
  270. // event.
  271. //
  272. void afterExcludeFromProjectEvent(string Guid, int ID, object CustomIn, object CustomOut)
  273. {
  274. try
  275. {
  276. if(String.IsNullOrEmpty(_excludedItem))
  277. {
  278. return;
  279. }
  280. Project p = getActiveProject();
  281. if(!Util.isCSharpProject(p) || !Util.isSliceBuilderEnabled(p))
  282. {
  283. return;
  284. }
  285. ProjectItem item = Util.findItem(_excludedItem, p.ProjectItems);
  286. if(item != null)
  287. {
  288. item.Delete();
  289. }
  290. updateDependencies(p);
  291. }
  292. catch(Exception ex)
  293. {
  294. Util.unexpectedExceptionWarning(ex);
  295. throw;
  296. }
  297. }
  298. //
  299. // In C# project type the delete event isn't triggered by exclude item command.
  300. // We use the before and after events of the command to remove generated items
  301. // when a slice file is excluded. C++ projects handle that as part of delete item
  302. // event.
  303. //
  304. public void beforeExcludeFromProjectEvent(string Guid, int ID, object obj, object CustomOut, ref bool done)
  305. {
  306. try
  307. {
  308. Project p = getActiveProject();
  309. if(!Util.isCSharpProject(p) || !Util.isSliceBuilderEnabled(p))
  310. {
  311. return;
  312. }
  313. ProjectItem item = Util.getSelectedProjectItem(p.DTE);
  314. if(item == null)
  315. {
  316. return;
  317. }
  318. if(!Util.isSliceFilename(item.Name))
  319. {
  320. return;
  321. }
  322. _excludedItem = getCSharpGeneratedFileName(p, item, "cs");
  323. return;
  324. }
  325. catch(Exception ex)
  326. {
  327. Util.write(null, Util.msgLevel.msgError, ex.ToString() + "\n");
  328. Util.unexpectedExceptionWarning(ex);
  329. throw;
  330. }
  331. }
  332. public IVsSolution getIVsSolution()
  333. {
  334. return (IVsSolution) _serviceProvider.GetService(typeof(IVsSolution));
  335. }
  336. public void buildDone(vsBuildScope Scope, vsBuildAction Action)
  337. {
  338. try
  339. {
  340. Util.solutionExplorerRefresh();
  341. _sliceBuild = false;
  342. //
  343. // If a Slice file has changed during the build, we rebuild that project's
  344. // Slice files now that the build is done.
  345. //
  346. List<Project> rebuildProjects = getRebuildProjects();
  347. foreach(Project p in rebuildProjects)
  348. {
  349. buildProject(p, false, vsBuildScope.vsBuildScopeProject, false);
  350. }
  351. rebuildProjects.Clear();
  352. }
  353. catch(Exception ex)
  354. {
  355. Util.unexpectedExceptionWarning(ex);
  356. throw;
  357. }
  358. finally
  359. {
  360. _buildProject = null;
  361. _building = false;
  362. }
  363. }
  364. //
  365. // Return true if the project build is in process.
  366. //
  367. public bool isBuilding(Project project)
  368. {
  369. if(!isBuilding())
  370. {
  371. return false;
  372. }
  373. if(_buildScope == vsBuildScope.vsBuildScopeSolution)
  374. {
  375. return true;
  376. }
  377. if(_buildScope == vsBuildScope.vsBuildScopeProject &&
  378. _buildProject == project)
  379. {
  380. return true;
  381. }
  382. return false;
  383. }
  384. //
  385. // Is our project building?
  386. //
  387. public bool isBuilding()
  388. {
  389. return _building;
  390. }
  391. //
  392. // If a Slice file created with "Add New Item" command cannot be added
  393. // to the project because the generated items will override an existing item,
  394. // the Slice file must be deleted from disk, here, after the command has
  395. // been executed.
  396. //
  397. public void afterAddNewItem(string Guid, int ID, object obj, object CustomOut)
  398. {
  399. try
  400. {
  401. foreach(String path in _deleted)
  402. {
  403. ProjectItem item = Util.findItem(path);
  404. if(item != null)
  405. {
  406. item.Remove();
  407. }
  408. if(String.IsNullOrEmpty(path))
  409. {
  410. continue;
  411. }
  412. if(File.Exists(path))
  413. {
  414. try
  415. {
  416. File.Delete(path);
  417. }
  418. catch(System.SystemException)
  419. {
  420. // Can happen if the file is used by another process.
  421. }
  422. }
  423. }
  424. _deleted.Clear();
  425. }
  426. catch(Exception ex)
  427. {
  428. Util.unexpectedExceptionWarning(ex);
  429. throw;
  430. }
  431. }
  432. //
  433. // If a Slice file added with "Add Existing Item" command cannot be added
  434. // to the project because the generated items will override an existing item,
  435. // the item must not be deleted here, we must empty the _deleted list so the
  436. // file isn't later removed.
  437. //
  438. public void afterAddExistingItem(string Guid, int ID, object obj, object CustomOut)
  439. {
  440. try
  441. {
  442. foreach (String path in _deleted)
  443. {
  444. ProjectItem item = Util.findItem(path);
  445. if(item != null)
  446. {
  447. item.Remove();
  448. }
  449. }
  450. _deleted.Clear();
  451. }
  452. catch(Exception ex)
  453. {
  454. Util.unexpectedExceptionWarning(ex);
  455. throw;
  456. }
  457. }
  458. public void afterBuildCancel(string Guid, int ID, object obj, object CustomOut)
  459. {
  460. try
  461. {
  462. Util.solutionExplorerRefresh();
  463. _sliceBuild = false;
  464. //
  465. // If a Slice file has changed during the build, we rebuild that project's
  466. // Slice files now that the build has been canceled.
  467. //
  468. List<Project> rebuildProjects = getRebuildProjects();
  469. foreach(Project p in rebuildProjects)
  470. {
  471. buildProject(p, false, vsBuildScope.vsBuildScopeProject, false);
  472. }
  473. rebuildProjects.Clear();
  474. }
  475. catch(Exception ex)
  476. {
  477. Util.unexpectedExceptionWarning(ex);
  478. throw;
  479. }
  480. finally
  481. {
  482. _buildProject = null;
  483. _building = false;
  484. }
  485. }
  486. public void setDebugEnvironmentStartupProject(string Guid, int ID, object obj, object CustomOut, ref bool done)
  487. {
  488. setDebugEnvironment(getStartupProject());
  489. }
  490. public void setDebugEnvironmentActiveProject(string Guid, int ID, object obj, object CustomOut, ref bool done)
  491. {
  492. setDebugEnvironment(getActiveProject());
  493. }
  494. public void setDebugEnvironment(Project project)
  495. {
  496. try
  497. {
  498. if(project != null && Util.isSliceBuilderEnabled(project))
  499. {
  500. if(Util.isCppProject(project))
  501. {
  502. VCProject vcProject = (VCProject)project.Object;
  503. IVCCollection configurations = (IVCCollection)vcProject.Configurations;
  504. foreach(VCConfiguration conf in configurations)
  505. {
  506. Util.addIceCppEnvironment((VCDebugSettings)conf.DebugSettings, project);
  507. }
  508. }
  509. else if(Util.isCSharpProject(project) || Util.isVBProject(project))
  510. {
  511. setDotNetDebugEnvironment(project);
  512. }
  513. }
  514. }
  515. catch(Exception ex)
  516. {
  517. Util.unexpectedExceptionWarning(ex);
  518. throw;
  519. }
  520. }
  521. //
  522. // Set DEVPATH if .NET development mode is enabled and project type is C# or VB,
  523. // otherwise do nothing.
  524. //
  525. // NOTE: for Silverlight projects we don't need to set DEVPATH.
  526. //
  527. private void setDotNetDebugEnvironment(Project project)
  528. {
  529. //
  530. // If development mode isn't enabled then don't set DEVPATH.
  531. //
  532. if(!Util.developmentMode(project))
  533. {
  534. return;
  535. }
  536. //
  537. // Check if vshosting process is enabled, if so disable it before updating
  538. // environment variables. If it is running it will be stopped.
  539. //
  540. bool vsHosting = false;
  541. if(Util.useVSHostingProcess(project))
  542. {
  543. Util.setVsHostingProcess(project, false);
  544. vsHosting = true;
  545. }
  546. setDotNetDevPath(Util.getCsBinDir(project));
  547. //
  548. // Re-enable the vshosting process if it was previously enabled,
  549. // so it reads the new environment when it is started by Visual Studio.
  550. //
  551. if(vsHosting)
  552. {
  553. Util.setVsHostingProcess(project, true);
  554. }
  555. }
  556. private static void setDotNetDevPath(string csBinPath)
  557. {
  558. string devPath = Environment.GetEnvironmentVariable("DEVPATH");
  559. if(String.IsNullOrEmpty(devPath))
  560. {
  561. Environment.SetEnvironmentVariable("DEVPATH", csBinPath);
  562. return;
  563. }
  564. if(devPath.Contains(csBinPath))
  565. {
  566. ComponentList list = new ComponentList(csBinPath.Split(Path.PathSeparator));
  567. list.Remove(csBinPath);
  568. devPath = list.ToString(Path.PathSeparator);
  569. }
  570. devPath = csBinPath + Path.PathSeparator + devPath;
  571. devPath = devPath.Trim(Path.PathSeparator);
  572. Environment.SetEnvironmentVariable("DEVPATH", devPath);
  573. }
  574. public void disconnect()
  575. {
  576. if(_iceConfigurationCmd != null)
  577. {
  578. _iceConfigurationCmd.Delete();
  579. }
  580. if(_connectMode != ext_ConnectMode.ext_cm_CommandLine)
  581. {
  582. _solutionEvents.Opened -= new _dispSolutionEvents_OpenedEventHandler(solutionOpened);
  583. _solutionEvents.AfterClosing -= new _dispSolutionEvents_AfterClosingEventHandler(afterClosing);
  584. _solutionEvents.ProjectAdded -= new _dispSolutionEvents_ProjectAddedEventHandler(projectAdded);
  585. _solutionEvents.ProjectRemoved -= new _dispSolutionEvents_ProjectRemovedEventHandler(projectRemoved);
  586. _solutionEvents.ProjectRenamed -= new _dispSolutionEvents_ProjectRenamedEventHandler(projectRenamed);
  587. _solutionEvents = null;
  588. }
  589. _buildEvents.OnBuildBegin -= new _dispBuildEvents_OnBuildBeginEventHandler(buildBegin);
  590. _buildEvents.OnBuildDone -= new _dispBuildEvents_OnBuildDoneEventHandler(buildDone);
  591. _buildEvents = null;
  592. if(_connectMode != ext_ConnectMode.ext_cm_CommandLine)
  593. {
  594. endTrackDocumentEvents();
  595. }
  596. if(_dependenciesMap != null)
  597. {
  598. _dependenciesMap.Clear();
  599. _dependenciesMap = null;
  600. }
  601. if(_rebuildProjects != null)
  602. {
  603. _rebuildProjects.Clear();
  604. _rebuildProjects = null;
  605. }
  606. _errorCount = 0;
  607. if(_errors != null)
  608. {
  609. _errors.Clear();
  610. _errors = null;
  611. }
  612. if(_fileTracker != null)
  613. {
  614. _fileTracker.clear();
  615. _fileTracker = null;
  616. }
  617. }
  618. private void setupCommandBars()
  619. {
  620. _iceConfigurationCmd = null;
  621. try
  622. {
  623. _iceConfigurationCmd =
  624. _applicationObject.Commands.Item(_addInInstance.ProgID + ".IceConfiguration", -1);
  625. }
  626. catch(ArgumentException)
  627. {
  628. object[] contextGUIDS = new object[] { };
  629. _iceConfigurationCmd =
  630. ((Commands2)_applicationObject.Commands).AddNamedCommand2(_addInInstance,
  631. "IceConfiguration",
  632. "Ice Configuration...",
  633. "Ice Configuration...",
  634. true, -1, ref contextGUIDS,
  635. (int)vsCommandStatus.vsCommandStatusSupported +
  636. (int)vsCommandStatus.vsCommandStatusEnabled,
  637. (int)vsCommandStyle.vsCommandStylePictAndText,
  638. vsCommandControlType.vsCommandControlTypeButton);
  639. }
  640. if(_iceConfigurationCmd == null)
  641. {
  642. MessageBox.Show("Error initializing Ice Visual Studio Add-in.\n" +
  643. "Cannot create required commands",
  644. "Ice Visual Studio Add-in",
  645. MessageBoxButtons.OK,
  646. MessageBoxIcon.Error,
  647. MessageBoxDefaultButton.Button1,
  648. (MessageBoxOptions)0);
  649. return;
  650. }
  651. CommandBar toolsCmdBar = ((CommandBars)_applicationObject.CommandBars)["Tools"];
  652. _iceConfigurationCmd.AddControl(toolsCmdBar, toolsCmdBar.Controls.Count + 1);
  653. CommandBar projectCmdBar = projectCommandBar();
  654. _iceConfigurationCmd.AddControl(projectCmdBar, projectCmdBar.Controls.Count + 1);
  655. }
  656. public void afterClosing()
  657. {
  658. try
  659. {
  660. clearErrors();
  661. removeDocumentEvents();
  662. if(_dependenciesMap != null)
  663. {
  664. _dependenciesMap.Clear();
  665. _dependenciesMap = null;
  666. }
  667. if(_rebuildProjects != null)
  668. {
  669. _rebuildProjects.Clear();
  670. _rebuildProjects = null;
  671. }
  672. }
  673. catch(Exception ex)
  674. {
  675. Util.unexpectedExceptionWarning(ex);
  676. throw;
  677. }
  678. finally
  679. {
  680. _opened = false;
  681. }
  682. }
  683. public void solutionOpened()
  684. {
  685. try
  686. {
  687. _opening = true;
  688. DependenciesMap dependenciesMap = getDependenciesMap();
  689. initDocumentEvents();
  690. }
  691. catch(Exception ex)
  692. {
  693. _opening = false;
  694. Util.unexpectedExceptionWarning(ex);
  695. throw;
  696. }
  697. Util.getCurrentDTE().StatusBar.Text = "Ready";
  698. _opening = false;
  699. _opened = false;
  700. }
  701. //
  702. // Enable slice builder for the project with default components.
  703. //
  704. public void addBuilderToProject(Project project)
  705. {
  706. addBuilderToProject(project, new ComponentList());
  707. }
  708. //
  709. // Enable Slice builder for the project, and enable the components that are
  710. // in components. If components list is empty, the default set of components
  711. // are added to the project.
  712. //
  713. // Note: Components in this context is the list of Ice libraries or assemblies
  714. // that will be added to the project.
  715. //
  716. public void addBuilderToProject(Project project, ComponentList components)
  717. {
  718. if(Util.isCppProject(project))
  719. {
  720. Util.addIceCppConfigurations(project);
  721. if(components.Count == 0)
  722. {
  723. components =
  724. new ComponentList(Util.getProjectProperty(project, Util.PropertyIceComponents));
  725. }
  726. if(!components.Contains("Ice"))
  727. {
  728. components.Add("Ice");
  729. }
  730. if(!Util.isWinRTProject(project))
  731. {
  732. if(!components.Contains("IceUtil"))
  733. {
  734. components.Add("IceUtil");
  735. }
  736. }
  737. Util.addIceCppLibs(project, components);
  738. }
  739. else
  740. {
  741. if(Util.isCSharpProject(project))
  742. {
  743. bool development = Util.developmentMode(project);
  744. if(components.Count == 0)
  745. {
  746. components =
  747. new ComponentList(Util.getProjectProperty(project, Util.PropertyIceComponents));
  748. }
  749. if(!components.Contains("Ice"))
  750. {
  751. components.Add("Ice");
  752. }
  753. string iceHome = Util.getIceHome();
  754. foreach(string component in components)
  755. {
  756. Util.addDotNetReference(project, component, development);
  757. }
  758. }
  759. else if(Util.isVBProject(project))
  760. {
  761. string iceHome = Util.getIceHome();
  762. bool development = Util.developmentMode(project);
  763. if(components.Count == 0)
  764. {
  765. components =
  766. new ComponentList(Util.getProjectProperty(project, Util.PropertyIceComponents));
  767. }
  768. if(!components.Contains("Ice"))
  769. {
  770. components.Add("Ice");
  771. }
  772. foreach(string component in components)
  773. {
  774. Util.addDotNetReference(project, component, development);
  775. }
  776. }
  777. }
  778. Util.setProjectProperty(project, Util.PropertyIceComponents, "");
  779. Util.setProjectProperty(project, Util.PropertyIce, true.ToString());
  780. if(hasErrors(project))
  781. {
  782. bringErrorsToFront();
  783. }
  784. }
  785. public void removeBuilderFromProject(Project project, ComponentList components)
  786. {
  787. cleanProject(project, true);
  788. if(Util.isCppProject(project))
  789. {
  790. Util.removeIceCppConfigurations(project);
  791. Util.setProjectProperty(project, Util.PropertyIceComponents, components.ToString());
  792. }
  793. else if(Util.isCSharpProject(project))
  794. {
  795. Util.removeDotNetReference(project, "Ice");
  796. }
  797. Util.setProjectProperty(project, Util.PropertyIceComponents, components.ToString());
  798. Util.setProjectProperty(project, Util.PropertyIce, false.ToString());
  799. }
  800. //
  801. // Ensure that generated items are opened in read only mode.
  802. //
  803. private void documentOpened(Document document)
  804. {
  805. try
  806. {
  807. if(document == null || document.ProjectItem == null || document.ProjectItem.ContainingProject == null)
  808. {
  809. return;
  810. }
  811. if(!Util.isSliceBuilderEnabled(document.ProjectItem.ContainingProject))
  812. {
  813. return;
  814. }
  815. if(fileTracker().hasGeneratedFile(document.ProjectItem.ContainingProject, document.FullName))
  816. {
  817. if(!document.ReadOnly)
  818. {
  819. document.ReadOnly = true;
  820. }
  821. }
  822. }
  823. catch(Exception ex)
  824. {
  825. Util.unexpectedExceptionWarning(ex);
  826. throw;
  827. }
  828. }
  829. public void documentSaved(Document document)
  830. {
  831. try
  832. {
  833. Project project = null;
  834. try
  835. {
  836. project = document.ProjectItem.ContainingProject;
  837. }
  838. catch(Exception)
  839. {
  840. //
  841. // Expected when documents are created during project initialization
  842. // and the ProjectItem is not yet available.
  843. //
  844. return;
  845. }
  846. if(!Util.isSliceBuilderEnabled(project))
  847. {
  848. return;
  849. }
  850. if(!Util.isSliceFilename(document.Name))
  851. {
  852. return;
  853. }
  854. //
  855. // If build is in proccess, we don't run the slice compiler now, we append the document
  856. // to a list of projects that have changes and return. The projects on this list
  857. // will be rebuilt when the current build process is done or canceled, see
  858. // "buildDone" and "afterBuildCancel" methods in this class.
  859. //
  860. if(isBuilding(project))
  861. {
  862. List<Project> rebuildProjects = getRebuildProjects();
  863. if(!rebuildProjects.Contains(project))
  864. {
  865. rebuildProjects.Add(project);
  866. }
  867. return;
  868. }
  869. clearErrors(project);
  870. buildProject(project, false, vsBuildScope.vsBuildScopeProject, false);
  871. Util.solutionExplorerRefresh();
  872. }
  873. catch(Exception ex)
  874. {
  875. Util.unexpectedExceptionWarning(ex);
  876. throw;
  877. }
  878. }
  879. public void projectAdded(Project project)
  880. {
  881. if(!_opened)
  882. {
  883. return;
  884. }
  885. try
  886. {
  887. if(Util.isSliceBuilderEnabled(project))
  888. {
  889. Util.verifyProjectSettings(project);
  890. updateDependencies(project);
  891. Util.solutionExplorerRefresh();
  892. }
  893. }
  894. catch(Exception ex)
  895. {
  896. Util.unexpectedExceptionWarning(ex);
  897. throw;
  898. }
  899. }
  900. public void projectRemoved(Project project)
  901. {
  902. try
  903. {
  904. DependenciesMap dependenciesMap = getDependenciesMap();
  905. if(dependenciesMap.ContainsKey(project.FullName))
  906. {
  907. dependenciesMap.Remove(project.FullName);
  908. }
  909. List<Project> rebuildProjects = getRebuildProjects();
  910. foreach(Project p in rebuildProjects)
  911. {
  912. if(project == p)
  913. {
  914. rebuildProjects.Remove(p);
  915. break;
  916. }
  917. }
  918. }
  919. catch(Exception ex)
  920. {
  921. Util.unexpectedExceptionWarning(ex);
  922. throw;
  923. }
  924. }
  925. public void projectRenamed(Project project, string oldName)
  926. {
  927. try
  928. {
  929. DependenciesMap dependenciesMap = getDependenciesMap();
  930. String oldPath = Path.Combine(Path.GetDirectoryName(project.FullName), oldName);
  931. if(dependenciesMap.ContainsKey(oldPath))
  932. {
  933. dependenciesMap.Remove(oldPath);
  934. }
  935. updateDependencies(project);
  936. }
  937. catch(Exception ex)
  938. {
  939. Util.unexpectedExceptionWarning(ex);
  940. throw;
  941. }
  942. }
  943. public void cleanProject(Project project, bool remove)
  944. {
  945. DTE dte = Util.getCurrentDTE();
  946. if(!_opening)
  947. {
  948. dte.StatusBar.Text = "Ice Add-in: cleaning project '" + project.FullName + "'";
  949. }
  950. if(project == null)
  951. {
  952. return;
  953. }
  954. if(!Util.isSliceBuilderEnabled(project))
  955. {
  956. return;
  957. }
  958. clearErrors(project);
  959. if(Util.isCSharpProject(project))
  960. {
  961. removeCSharpGeneratedItems(project, project.ProjectItems, remove);
  962. }
  963. else if(Util.isCppProject(project))
  964. {
  965. removeCppGeneratedItems(project.ProjectItems, remove);
  966. }
  967. if(!_opening)
  968. {
  969. dte.StatusBar.Text = "Ready";
  970. }
  971. }
  972. public void removeCSharpGeneratedItems(Project project, ProjectItems items, bool remove)
  973. {
  974. if(project == null)
  975. {
  976. return;
  977. }
  978. if(items == null)
  979. {
  980. return;
  981. }
  982. List<ProjectItem> tmpItems = Util.clone(items);
  983. foreach(ProjectItem i in tmpItems)
  984. {
  985. if(i == null)
  986. {
  987. continue;
  988. }
  989. if(Util.isProjectItemFolder(i))
  990. {
  991. removeCSharpGeneratedItems(project, i.ProjectItems, remove);
  992. }
  993. else if(Util.isProjectItemFile(i))
  994. {
  995. removeCSharpGeneratedItems(i, remove);
  996. }
  997. }
  998. }
  999. public void buildProject(Project project, bool force, vsBuildScope scope, bool buildDependencies)
  1000. {
  1001. List<Project> builded = new List<Project>();
  1002. buildProject(project, force, null, scope, buildDependencies, ref builded);
  1003. }
  1004. public void buildProject(Project project, bool force, vsBuildScope scope, bool buildDependencies, ref List<Project> builded)
  1005. {
  1006. buildProject(project, force, null, scope, buildDependencies, ref builded);
  1007. }
  1008. public void buildProject(Project project, bool force, ProjectItem excludeItem, vsBuildScope scope, bool buildDependencies)
  1009. {
  1010. List<Project> builded = new List<Project>();
  1011. buildProject(project, force, excludeItem, scope, buildDependencies, ref builded);
  1012. }
  1013. public void buildProject(Project project, bool force, ProjectItem excludeItem, vsBuildScope scope, bool buildDependencies,
  1014. ref List<Project> builded)
  1015. {
  1016. if(project == null)
  1017. {
  1018. return;
  1019. }
  1020. if(!Util.isSliceBuilderEnabled(project))
  1021. {
  1022. return;
  1023. }
  1024. if(builded.Contains(project))
  1025. {
  1026. return;
  1027. }
  1028. if(_deleted.Count > 0)
  1029. {
  1030. return;
  1031. }
  1032. initializeProject(project);
  1033. builded.Add(project);
  1034. List<ProjectItem> buildItems = new List<ProjectItem>();
  1035. //
  1036. // When building a single project, we must first build projects
  1037. // that this project depends on.
  1038. //
  1039. if(vsBuildScope.vsBuildScopeProject == scope && buildDependencies)
  1040. {
  1041. BuildDependencies dependencies = _applicationObject.Solution.SolutionBuild.BuildDependencies;
  1042. for(int i = 0; i < dependencies.Count; ++i)
  1043. {
  1044. BuildDependency dp = dependencies.Item(i + 1);
  1045. if(dp == null)
  1046. {
  1047. continue;
  1048. }
  1049. if(dp.Project.Equals(project))
  1050. {
  1051. System.Array projects = dp.RequiredProjects as System.Array;
  1052. if(projects != null)
  1053. {
  1054. foreach(Project p in projects)
  1055. {
  1056. buildProject(p, force, vsBuildScope.vsBuildScopeProject, buildDependencies, ref builded);
  1057. }
  1058. }
  1059. }
  1060. }
  1061. }
  1062. if(Util.isVBProject(project))
  1063. {
  1064. //
  1065. // For VB projects we just build dependencies.
  1066. //
  1067. return;
  1068. }
  1069. DTE dte = Util.getCurrentDTE();
  1070. if(!_opening)
  1071. {
  1072. dte.StatusBar.Text = "Ice Add-in: building project '" + project.FullName + "'";
  1073. }
  1074. string msg = "------ Slice compilation started " + "Project: " + Util.getTraceProjectName(project) + " ------\n";
  1075. Util.write(project, Util.msgLevel.msgInfo, msg);
  1076. int verboseLevel = Util.getVerboseLevel(project);
  1077. DateTime now = DateTime.Now;
  1078. if(verboseLevel >= (int)Util.msgLevel.msgDebug)
  1079. {
  1080. Util.write(project, Util.msgLevel.msgDebug, "DEBUG Start Time: " + now.ToShortDateString() + " " +
  1081. now.ToLongTimeString() + "\n");
  1082. }
  1083. if(Util.isCSharpProject(project))
  1084. {
  1085. buildCSharpProject(project, force, excludeItem);
  1086. }
  1087. else if(Util.isCppProject(project))
  1088. {
  1089. buildCppProject(project, force, ref buildItems);
  1090. }
  1091. if(verboseLevel >= (int)Util.msgLevel.msgDebug)
  1092. {
  1093. System.TimeSpan t = System.DateTime.Now - now;
  1094. Util.write(project, Util.msgLevel.msgDebug, "DEBUG Output:\n");
  1095. Util.write(project, Util.msgLevel.msgDebug, "DEBUG Time Elapsed: " + t.ToString() + "\n");
  1096. }
  1097. if(hasErrors(project))
  1098. {
  1099. Util.write(project, Util.msgLevel.msgError,
  1100. "------ Slice compilation failed: Project: " + Util.getTraceProjectName(project) +" ------\n\n");
  1101. }
  1102. else
  1103. {
  1104. Util.write(project, Util.msgLevel.msgInfo,
  1105. "------ Slice compilation succeeded: Project: " + Util.getTraceProjectName(project) + " ------\n\n");
  1106. }
  1107. if(!_opening)
  1108. {
  1109. dte.StatusBar.Text = "Ready";
  1110. }
  1111. }
  1112. public bool buildCppProject(Project project, bool force, ref List<ProjectItem> buildedItems)
  1113. {
  1114. VCConfiguration conf = Util.getActiveVCConfiguration(project);
  1115. if(conf.ConfigurationType == ConfigurationTypes.typeGeneric ||
  1116. conf.ConfigurationType == ConfigurationTypes.typeUnknown)
  1117. {
  1118. string err = "Configuration Type: '" + conf.ConfigurationType.ToString() + "' not supported by Ice Visual Studio Add-in";
  1119. Util.write(project, Util.msgLevel.msgError,
  1120. "------ Slice compilation failed: Project: " + Util.getTraceProjectName(project) + " ------\n\n" +
  1121. err);
  1122. MessageBox.Show(err, "Ice Visual Studio Add-in", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1,
  1123. (MessageBoxOptions)0);
  1124. Connect.getBuilder().addError(project, "", TaskErrorCategory.Error, 0, 0, err);
  1125. return false;
  1126. }
  1127. VCCLCompilerTool compilerTool =
  1128. (VCCLCompilerTool)(((IVCCollection)conf.Tools).Item("VCCLCompilerTool"));
  1129. bool staticLib = conf.ConfigurationType == Microsoft.VisualStudio.VCProjectEngine.ConfigurationTypes.typeStaticLibrary;
  1130. LinkerAdapter linkerAdapter;
  1131. if(staticLib)
  1132. {
  1133. linkerAdapter = new StaticLinkerAdapter((VCLibrarianTool)(((IVCCollection)conf.Tools).Item("VCLibrarianTool")));
  1134. }
  1135. else
  1136. {
  1137. linkerAdapter = new DynamicLinkerAdapter((VCLinkerTool)(((IVCCollection)conf.Tools).Item("VCLinkerTool")));
  1138. }
  1139. if(!_opening)
  1140. {
  1141. Util.checkCppRunTimeLibrary(this, project, compilerTool, linkerAdapter);
  1142. }
  1143. string sliceCompiler = getSliceCompilerPath(project);
  1144. return buildCppProject(project, project.ProjectItems, sliceCompiler, force, ref buildedItems);
  1145. }
  1146. public bool buildCppProject(Project project, ProjectItems items, string sliceCompiler, bool force,
  1147. ref List<ProjectItem> buildedItems)
  1148. {
  1149. bool success = true;
  1150. List<ProjectItem> tmpItems = Util.clone(items);
  1151. foreach(ProjectItem i in tmpItems)
  1152. {
  1153. if(i == null)
  1154. {
  1155. continue;
  1156. }
  1157. if(Util.isProjectItemFilter(i))
  1158. {
  1159. if(!buildCppProject(project, i.ProjectItems, sliceCompiler, force, ref buildedItems))
  1160. {
  1161. success = false;
  1162. }
  1163. }
  1164. else if(Util.isProjectItemFile(i))
  1165. {
  1166. if(!buildCppProjectItem(project, i, sliceCompiler, force, ref buildedItems))
  1167. {
  1168. success = false;
  1169. }
  1170. }
  1171. }
  1172. return success;
  1173. }
  1174. public bool buildCppProjectItem(Project project, ProjectItem item, string sliceCompiler, bool force,
  1175. ref List<ProjectItem> buildedItems)
  1176. {
  1177. if(project == null)
  1178. {
  1179. return true;
  1180. }
  1181. if(item == null)
  1182. {
  1183. return true;
  1184. }
  1185. if(item.Name == null)
  1186. {
  1187. return true;
  1188. }
  1189. if(!Util.isSliceFilename(item.Name))
  1190. {
  1191. return true;
  1192. }
  1193. FileInfo iceFileInfo = new FileInfo(item.Properties.Item("FullPath").Value.ToString());
  1194. FileInfo hFileInfo = new FileInfo(getCppGeneratedFileName(project,
  1195. iceFileInfo.FullName, Util.getHeaderExt(project)));
  1196. FileInfo cppFileInfo = new FileInfo(Path.ChangeExtension(hFileInfo.FullName, Util.getSourceExt(project)));
  1197. string output = Path.GetDirectoryName(cppFileInfo.FullName);
  1198. return buildCppProjectItem(project, output, iceFileInfo, cppFileInfo, hFileInfo, sliceCompiler, force,
  1199. ref buildedItems);
  1200. }
  1201. public bool buildCppProjectItem(Project project, String output, FileSystemInfo ice, FileSystemInfo cpp,
  1202. FileSystemInfo h, string sliceCompiler, bool force,
  1203. ref List<ProjectItem> buildedItems)
  1204. {
  1205. bool updated = false;
  1206. bool success = false;
  1207. if(!h.Exists || !cpp.Exists)
  1208. {
  1209. updated = true;
  1210. }
  1211. else if(Util.findItem(h.FullName, project.ProjectItems) == null ||
  1212. Util.findItem(cpp.FullName, project.ProjectItems) == null)
  1213. {
  1214. updated = true;
  1215. }
  1216. else if(ice.LastWriteTime > h.LastWriteTime || ice.LastWriteTime > cpp.LastWriteTime)
  1217. {
  1218. if(!Directory.Exists(output))
  1219. {
  1220. Directory.CreateDirectory(output);
  1221. }
  1222. updated = true;
  1223. }
  1224. else
  1225. {
  1226. //
  1227. // Now check if any of the dependencies have changed.
  1228. //
  1229. DependenciesMap solutionDependenciesMap = getDependenciesMap();
  1230. if(solutionDependenciesMap.ContainsKey(project.FullName))
  1231. {
  1232. Dictionary<string, List<string>> dependenciesMap = solutionDependenciesMap[project.FullName];
  1233. if(dependenciesMap.ContainsKey(ice.FullName))
  1234. {
  1235. List<string> fileDependencies = dependenciesMap[ice.FullName];
  1236. foreach(string name in fileDependencies)
  1237. {
  1238. FileInfo dependency = new FileInfo(Util.absolutePath(project, name));
  1239. if(!dependency.Exists)
  1240. {
  1241. updated = true;
  1242. break;
  1243. }
  1244. if(dependency.LastWriteTime > cpp.LastWriteTime ||

Large files files are truncated, but you can click here to view the full file