25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

369 satır
12 KiB

  1. 'use strict';
  2. import { commands, ConfigurationChangeEvent, Disposable, ExtensionContext, Uri } from 'vscode';
  3. import { FileAnnotationController } from './annotations/fileAnnotationController';
  4. import { LineAnnotationController } from './annotations/lineAnnotationController';
  5. import { GitCodeLensController } from './codelens/codeLensController';
  6. import { Commands, ToggleFileBlameCommandArgs } from './commands';
  7. import { AnnotationsToggleMode, Config, configuration, ConfigurationWillChangeEvent } from './configuration';
  8. import { GitFileSystemProvider } from './git/fsProvider';
  9. import { GitService } from './git/gitService';
  10. import { clearAvatarCache } from './avatars';
  11. import { LineHoverController } from './hovers/lineHoverController';
  12. import { Keyboard } from './keyboard';
  13. import { Logger } from './logger';
  14. import { StatusBarController } from './statusbar/statusBarController';
  15. import { GitDocumentTracker } from './trackers/gitDocumentTracker';
  16. import { GitLineTracker } from './trackers/gitLineTracker';
  17. import { CompareView } from './views/compareView';
  18. import { FileHistoryView } from './views/fileHistoryView';
  19. import { LineHistoryView } from './views/lineHistoryView';
  20. import { RepositoriesView } from './views/repositoriesView';
  21. import { SearchView } from './views/searchView';
  22. import { ViewCommands } from './views/viewCommands';
  23. import { VslsController } from './vsls/vsls';
  24. import { SettingsWebview } from './webviews/settingsWebview';
  25. import { WelcomeWebview } from './webviews/welcomeWebview';
  26. export class Container {
  27. private static _configsAffectedByMode: string[] | undefined;
  28. private static _applyModeConfigurationTransformBound:
  29. | ((e: ConfigurationChangeEvent) => ConfigurationChangeEvent)
  30. | undefined;
  31. static initialize(context: ExtensionContext, config: Config) {
  32. this._context = context;
  33. this._config = Container.applyMode(config);
  34. context.subscriptions.push((this._lineTracker = new GitLineTracker()));
  35. context.subscriptions.push((this._tracker = new GitDocumentTracker()));
  36. context.subscriptions.push((this._vsls = new VslsController()));
  37. context.subscriptions.push((this._git = new GitService()));
  38. // Since there is a bit of a chicken & egg problem with the DocumentTracker and the GitService, initialize the tracker once the GitService is loaded
  39. this._tracker.initialize();
  40. context.subscriptions.push((this._fileAnnotationController = new FileAnnotationController()));
  41. context.subscriptions.push((this._lineAnnotationController = new LineAnnotationController()));
  42. context.subscriptions.push((this._lineHoverController = new LineHoverController()));
  43. context.subscriptions.push((this._statusBarController = new StatusBarController()));
  44. context.subscriptions.push((this._codeLensController = new GitCodeLensController()));
  45. context.subscriptions.push((this._keyboard = new Keyboard()));
  46. context.subscriptions.push((this._settingsWebview = new SettingsWebview()));
  47. context.subscriptions.push((this._welcomeWebview = new WelcomeWebview()));
  48. if (config.views.compare.enabled) {
  49. context.subscriptions.push((this._compareView = new CompareView()));
  50. } else {
  51. let disposable: Disposable;
  52. // eslint-disable-next-line prefer-const
  53. disposable = configuration.onDidChange(e => {
  54. if (configuration.changed(e, 'views', 'compare', 'enabled')) {
  55. disposable.dispose();
  56. context.subscriptions.push((this._compareView = new CompareView()));
  57. }
  58. });
  59. }
  60. if (config.views.fileHistory.enabled) {
  61. context.subscriptions.push((this._fileHistoryView = new FileHistoryView()));
  62. } else {
  63. let disposable: Disposable;
  64. // eslint-disable-next-line prefer-const
  65. disposable = configuration.onDidChange(e => {
  66. if (configuration.changed(e, 'views', 'fileHistory', 'enabled')) {
  67. disposable.dispose();
  68. context.subscriptions.push((this._fileHistoryView = new FileHistoryView()));
  69. }
  70. });
  71. }
  72. if (config.views.lineHistory.enabled) {
  73. context.subscriptions.push((this._lineHistoryView = new LineHistoryView()));
  74. } else {
  75. let disposable: Disposable;
  76. // eslint-disable-next-line prefer-const
  77. disposable = configuration.onDidChange(e => {
  78. if (configuration.changed(e, 'views', 'lineHistory', 'enabled')) {
  79. disposable.dispose();
  80. context.subscriptions.push((this._lineHistoryView = new LineHistoryView()));
  81. }
  82. });
  83. }
  84. if (config.views.repositories.enabled) {
  85. context.subscriptions.push((this._repositoriesView = new RepositoriesView()));
  86. } else {
  87. let disposable: Disposable;
  88. // eslint-disable-next-line prefer-const
  89. disposable = configuration.onDidChange(e => {
  90. if (configuration.changed(e, 'views', 'repositories', 'enabled')) {
  91. disposable.dispose();
  92. context.subscriptions.push((this._repositoriesView = new RepositoriesView()));
  93. }
  94. });
  95. }
  96. if (config.views.search.enabled) {
  97. context.subscriptions.push((this._searchView = new SearchView()));
  98. } else {
  99. let disposable: Disposable;
  100. // eslint-disable-next-line prefer-const
  101. disposable = configuration.onDidChange(e => {
  102. if (configuration.changed(e, 'views', 'search', 'enabled')) {
  103. disposable.dispose();
  104. context.subscriptions.push((this._searchView = new SearchView()));
  105. }
  106. });
  107. }
  108. context.subscriptions.push(new GitFileSystemProvider());
  109. context.subscriptions.push(configuration.onWillChange(this.onConfigurationChanging, this));
  110. }
  111. private static onConfigurationChanging(e: ConfigurationWillChangeEvent) {
  112. this._config = undefined;
  113. if (configuration.changed(e.change, 'outputLevel')) {
  114. Logger.level = configuration.get('outputLevel');
  115. }
  116. if (configuration.changed(e.change, 'defaultGravatarsStyle')) {
  117. clearAvatarCache();
  118. }
  119. if (configuration.changed(e.change, 'mode') || configuration.changed(e.change, 'modes')) {
  120. if (this._applyModeConfigurationTransformBound === undefined) {
  121. this._applyModeConfigurationTransformBound = this.applyModeConfigurationTransform.bind(this);
  122. }
  123. e.transform = this._applyModeConfigurationTransformBound;
  124. }
  125. }
  126. private static _codeLensController: GitCodeLensController;
  127. static get codeLens() {
  128. return this._codeLensController;
  129. }
  130. private static _compareView: CompareView | undefined;
  131. static get compareView() {
  132. if (this._compareView === undefined) {
  133. this._context.subscriptions.push((this._compareView = new CompareView()));
  134. }
  135. return this._compareView;
  136. }
  137. private static _config: Config | undefined;
  138. static get config() {
  139. if (this._config === undefined) {
  140. this._config = Container.applyMode(configuration.get());
  141. }
  142. return this._config;
  143. }
  144. private static _context: ExtensionContext;
  145. static get context() {
  146. return this._context;
  147. }
  148. private static _fileAnnotationController: FileAnnotationController;
  149. static get fileAnnotations() {
  150. return this._fileAnnotationController;
  151. }
  152. private static _fileHistoryView: FileHistoryView | undefined;
  153. static get fileHistoryView() {
  154. if (this._fileHistoryView === undefined) {
  155. this._context.subscriptions.push((this._fileHistoryView = new FileHistoryView()));
  156. }
  157. return this._fileHistoryView;
  158. }
  159. private static _git: GitService;
  160. static get git() {
  161. return this._git;
  162. }
  163. private static _keyboard: Keyboard;
  164. static get keyboard() {
  165. return this._keyboard;
  166. }
  167. private static _lineAnnotationController: LineAnnotationController;
  168. static get lineAnnotations() {
  169. return this._lineAnnotationController;
  170. }
  171. private static _lineHistoryView: LineHistoryView | undefined;
  172. static get lineHistoryView() {
  173. if (this._lineHistoryView === undefined) {
  174. this._context.subscriptions.push((this._lineHistoryView = new LineHistoryView()));
  175. }
  176. return this._lineHistoryView;
  177. }
  178. private static _lineHoverController: LineHoverController;
  179. static get lineHovers() {
  180. return this._lineHoverController;
  181. }
  182. private static _lineTracker: GitLineTracker;
  183. static get lineTracker() {
  184. return this._lineTracker;
  185. }
  186. private static _repositoriesView: RepositoriesView | undefined;
  187. static get repositoriesView(): RepositoriesView {
  188. if (this._repositoriesView === undefined) {
  189. this._context.subscriptions.push((this._repositoriesView = new RepositoriesView()));
  190. }
  191. return this._repositoriesView;
  192. }
  193. private static _searchView: SearchView | undefined;
  194. static get searchView() {
  195. if (this._searchView === undefined) {
  196. this._context.subscriptions.push((this._searchView = new SearchView()));
  197. }
  198. return this._searchView;
  199. }
  200. private static _settingsWebview: SettingsWebview;
  201. static get settingsWebview() {
  202. return this._settingsWebview;
  203. }
  204. private static _statusBarController: StatusBarController;
  205. static get statusBar() {
  206. return this._statusBarController;
  207. }
  208. private static _tracker: GitDocumentTracker;
  209. static get tracker() {
  210. return this._tracker;
  211. }
  212. private static _viewCommands: ViewCommands | undefined;
  213. static get viewCommands() {
  214. if (this._viewCommands === undefined) {
  215. this._viewCommands = new ViewCommands();
  216. }
  217. return this._viewCommands;
  218. }
  219. private static _vsls: VslsController;
  220. static get vsls() {
  221. return this._vsls;
  222. }
  223. private static _welcomeWebview: WelcomeWebview;
  224. static get welcomeWebview() {
  225. return this._welcomeWebview;
  226. }
  227. private static applyMode(config: Config) {
  228. if (!config.mode.active) return config;
  229. const mode = config.modes[config.mode.active];
  230. if (mode == null) return config;
  231. if (mode.annotations != null) {
  232. let command: string | undefined;
  233. switch (mode.annotations) {
  234. case 'blame':
  235. config.blame.toggleMode = AnnotationsToggleMode.Window;
  236. command = Commands.ToggleFileBlame;
  237. break;
  238. case 'heatmap':
  239. config.heatmap.toggleMode = AnnotationsToggleMode.Window;
  240. command = Commands.ToggleFileHeatmap;
  241. break;
  242. case 'recentChanges':
  243. config.recentChanges.toggleMode = AnnotationsToggleMode.Window;
  244. command = Commands.ToggleFileRecentChanges;
  245. break;
  246. }
  247. if (command !== undefined) {
  248. const commandArgs: ToggleFileBlameCommandArgs = {
  249. on: true
  250. };
  251. // Make sure to delay the execution by a bit so that the configuration changes get propegated first
  252. setTimeout(() => commands.executeCommand(command!, commandArgs), 50);
  253. }
  254. }
  255. if (mode.codeLens != null) {
  256. config.codeLens.enabled = mode.codeLens;
  257. }
  258. if (mode.currentLine != null) {
  259. config.currentLine.enabled = mode.currentLine;
  260. }
  261. if (mode.hovers != null) {
  262. config.hovers.enabled = mode.hovers;
  263. }
  264. if (mode.statusBar != null) {
  265. config.statusBar.enabled = mode.statusBar;
  266. }
  267. if (mode.views != null) {
  268. config.views.compare.enabled = mode.views;
  269. }
  270. if (mode.views != null) {
  271. config.views.fileHistory.enabled = mode.views;
  272. }
  273. if (mode.views != null) {
  274. config.views.lineHistory.enabled = mode.views;
  275. }
  276. if (mode.views != null) {
  277. config.views.repositories.enabled = mode.views;
  278. }
  279. if (mode.views != null) {
  280. config.views.search.enabled = mode.views;
  281. }
  282. return config;
  283. }
  284. private static applyModeConfigurationTransform(e: ConfigurationChangeEvent): ConfigurationChangeEvent {
  285. if (this._configsAffectedByMode === undefined) {
  286. this._configsAffectedByMode = [
  287. `gitlens.${configuration.name('mode')}`,
  288. `gitlens.${configuration.name('modes')}`,
  289. `gitlens.${configuration.name('blame', 'toggleMode')}`,
  290. `gitlens.${configuration.name('codeLens')}`,
  291. `gitlens.${configuration.name('currentLine')}`,
  292. `gitlens.${configuration.name('heatmap', 'toggleMode')}`,
  293. `gitlens.${configuration.name('hovers')}`,
  294. `gitlens.${configuration.name('recentChanges', 'toggleMode')}`,
  295. `gitlens.${configuration.name('statusBar')}`,
  296. `gitlens.${configuration.name('views', 'compare')}`,
  297. `gitlens.${configuration.name('views', 'fileHistory')}`,
  298. `gitlens.${configuration.name('views', 'lineHistory')}`,
  299. `gitlens.${configuration.name('views', 'repositories')}`,
  300. `gitlens.${configuration.name('views', 'search')}`
  301. ];
  302. }
  303. const original = e.affectsConfiguration;
  304. return {
  305. ...e,
  306. affectsConfiguration: (section: string, resource?: Uri) => {
  307. if (this._configsAffectedByMode && this._configsAffectedByMode.some(n => section.startsWith(n))) {
  308. return true;
  309. }
  310. return original(section, resource);
  311. }
  312. };
  313. }
  314. }