text: /*---------------------------------------------------------------------------------------------
   *  Copyright (c) Microsoft Corporation. All rights reserved.
   *  Licensed under the MIT License. See License.txt in the project root for license information.
   *--------------------------------------------------------------------------------------------*/
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
      var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
      if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
      else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
      return c > 3 && r && Object.defineProperty(target, key, r), r;
  };
  var __param = (this && this.__param) || function (paramIndex, decorator) {
      return function (target, key) { decorator(target, key, paramIndex); }
  };
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
      function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
      return new (P || (P = Promise))(function (resolve, reject) {
          function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
          function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
          function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
          step((generator = generator.apply(thisArg, _arguments || [])).next());
      });
  };
  import * as dom from '../../../../base/browser/dom.js';
  import { Sizing, SplitView } from '../../../../base/browser/ui/splitview/splitview.js';
  import { Color } from '../../../../base/common/color.js';
  import { Emitter, Event } from '../../../../base/common/event.js';
  import { DisposableStore, dispose } from '../../../../base/common/lifecycle.js';
  import { Schemas } from '../../../../base/common/network.js';
  import { basenameOrAuthority, dirname } from '../../../../base/common/resources.js';
  import './referencesWidget.css';
  import { EmbeddedCodeEditorWidget } from '../../../browser/widget/embeddedCodeEditorWidget.js';
  import { Range } from '../../../common/core/range.js';
  import { ModelDecorationOptions, TextModel } from '../../../common/model/textModel.js';
  import { ILanguageConfigurationService } from '../../../common/modes/languageConfigurationRegistry.js';
  import { IModeService } from '../../../common/services/modeService.js';
  import { ITextModelService } from '../../../common/services/resolverService.js';
  import { AccessibilityProvider, DataSource, Delegate, FileReferencesRenderer, IdentityProvider, OneReferenceRenderer, StringRepresentationProvider } from './referencesTree.js';
  import * as peekView from '../../peekView/peekView.js';
  import * as nls from '../../../../nls.js';
  import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
  import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js';
  import { ILabelService } from '../../../../platform/label/common/label.js';
  import { WorkbenchAsyncDataTree } from '../../../../platform/list/browser/listService.js';
  import { IThemeService } from '../../../../platform/theme/common/themeService.js';
  import { IUndoRedoService } from '../../../../platform/undoRedo/common/undoRedo.js';
  import { FileReferences, OneReference } from '../referencesModel.js';
  class DecorationsManager {
      constructor(_editor, _model) {
          this._editor = _editor;
          this._model = _model;
          this._decorations = new Map();
          this._decorationIgnoreSet = new Set();
          this._callOnDispose = new DisposableStore();
          this._callOnModelChange = new DisposableStore();
          this._callOnDispose.add(this._editor.onDidChangeModel(() => this._onModelChanged()));
          this._onModelChanged();
      }
      dispose() {
          this._callOnModelChange.dispose();
          this._callOnDispose.dispose();
          this.removeDecorations();
      }
      _onModelChanged() {
          this._callOnModelChange.clear();
          const model = this._editor.getModel();
          if (!model) {
              return;
          }
          for (let ref of this._model.references) {
              if (ref.uri.toString() === model.uri.toString()) {
                  this._addDecorations(ref.parent);
                  return;
              }
          }
      }
      _addDecorations(reference) {
          if (!this._editor.hasModel()) {
              return;
          }
          this._callOnModelChange.add(this._editor.getModel().onDidChangeDecorations(() => this._onDecorationChanged()));
          const newDecorations = [];
          const newDecorationsActualIndex = [];
          for (let i = 0, len = reference.children.length; i < len; i++) {
              let oneReference = reference.children[i];
              if (this._decorationIgnoreSet.has(oneReference.id)) {
                  continue;
              }
              if (oneReference.uri.toString() !== this._editor.getModel().uri.toString()) {
                  continue;
              }
              newDecorations.push({
                  range: oneReference.range,
                  options: DecorationsManager.DecorationOptions
              });
              newDecorationsActualIndex.push(i);
          }
          const decorations = this._editor.deltaDecorations([], newDecorations);
          for (let i = 0; i < decorations.length; i++) {
              this._decorations.set(decorations[i], reference.children[newDecorationsActualIndex[i]]);
          }
      }
      _onDecorationChanged() {
          const toRemove = [];
          const model = this._editor.getModel();
          if (!model) {
              return;
          }
          for (let [decorationId, reference] of this._decorations) {
              const newRange = model.getDecorationRange(decorationId);
              if (!newRange) {
                  continue;
              }
              let ignore = false;
              if (Range.equalsRange(newRange, reference.range)) {
                  continue;
              }
              if (Range.spansMultipleLines(newRange)) {
                  ignore = true;
              }
              else {
                  const lineLength = reference.range.endColumn - reference.range.startColumn;
                  const newLineLength = newRange.endColumn - newRange.startColumn;
                  if (lineLength !== newLineLength) {
                      ignore = true;
                  }
              }
              if (ignore) {
                  this._decorationIgnoreSet.add(reference.id);
                  toRemove.push(decorationId);
              }
              else {
                  reference.range = newRange;
              }
          }
          for (let i = 0, len = toRemove.length; i < len; i++) {
              this._decorations.delete(toRemove[i]);
          }
          this._editor.deltaDecorations(toRemove, []);
      }
      removeDecorations() {
          this._editor.deltaDecorations([...this._decorations.keys()], []);
          this._decorations.clear();
      }
  }
  DecorationsManager.DecorationOptions = ModelDecorationOptions.register({
      description: 'reference-decoration',
      stickiness: 1 /* NeverGrowsWhenTypingAtEdges */,
      className: 'reference-decoration'
  });
  export class LayoutData {
      constructor() {
          this.ratio = 0.7;
          this.heightInLines = 18;
      }
      static fromJSON(raw) {
          let ratio;
          let heightInLines;
          try {
              const data = JSON.parse(raw);
              ratio = data.ratio;
              heightInLines = data.heightInLines;
          }
          catch (_a) {
              //
          }
          return {
              ratio: ratio || 0.7,
              heightInLines: heightInLines || 18
          };
      }
  }
  class ReferencesTree extends WorkbenchAsyncDataTree {
  }
  /**
   * ZoneWidget that is shown inside the editor
   */
  let ReferenceWidget = class ReferenceWidget extends peekView.PeekViewWidget {
      constructor(editor, _defaultTreeKeyboardSupport, layoutData, themeService, _textModelResolverService, _instantiationService, _peekViewService, _uriLabel, _undoRedoService, _keybindingService, _modeService, _languageConfigurationService) {
          super(editor, { showFrame: false, showArrow: true, isResizeable: true, isAccessible: true, supportOnTitleClick: true }, _instantiationService);
          this._defaultTreeKeyboardSupport = _defaultTreeKeyboardSupport;
          this.layoutData = layoutData;
          this._textModelResolverService = _textModelResolverService;
          this._instantiationService = _instantiationService;
          this._peekViewService = _peekViewService;
          this._uriLabel = _uriLabel;
          this._undoRedoService = _undoRedoService;
          this._keybindingService = _keybindingService;
          this._modeService = _modeService;
          this._languageConfigurationService = _languageConfigurationService;
          this._disposeOnNewModel = new DisposableStore();
          this._callOnDispose = new DisposableStore();
          this._onDidSelectReference = new Emitter();
          this.onDidSelectReference = this._onDidSelectReference.event;
          this._dim = new dom.Dimension(0, 0);
          this._applyTheme(themeService.getColorTheme());
          this._callOnDispose.add(themeService.onDidColorThemeChange(this._applyTheme.bind(this)));
          this._peekViewService.addExclusiveWidget(editor, this);
          this.create();
      }
      dispose() {
          this.setModel(undefined);
          this._callOnDispose.dispose();
          this._disposeOnNewModel.dispose();
          dispose(this._preview);
          dispose(this._previewNotAvailableMessage);
          dispose(this._tree);
          dispose(this._previewModelReference);
          this._splitView.dispose();
          super.dispose();
      }
      _applyTheme(theme) {
          const borderColor = theme.getColor(peekView.peekViewBorder) || Color.transparent;
          this.style({
              arrowColor: borderColor,
              frameColor: borderColor,
              headerBackgroundColor: theme.getColor(peekView.peekViewTitleBackground) || Color.transparent,
              primaryHeadingColor: theme.getColor(peekView.peekViewTitleForeground),
              secondaryHeadingColor: theme.getColor(peekView.peekViewTitleInfoForeground)
          });
      }
      show(where) {
          this.editor.revealRangeInCenterIfOutsideViewport(where, 0 /* Smooth */);
          super.show(where, this.layoutData.heightInLines || 18);
      }
      focusOnReferenceTree() {
          this._tree.domFocus();
      }
      focusOnPreviewEditor() {
          this._preview.focus();
      }
      isPreviewEditorFocused() {
          return this._preview.hasTextFocus();
      }
      _onTitleClick(e) {
          if (this._preview && this._preview.getModel()) {
              this._onDidSelectReference.fire({
                  element: this._getFocusedReference(),
                  kind: e.ctrlKey || e.metaKey || e.altKey ? 'side' : 'open',
                  source: 'title'
              });
          }
      }
      _fillBody(containerElement) {
          this.setCssClass('reference-zone-widget');
          // message pane
          this._messageContainer = dom.append(containerElement, dom.$('div.messages'));
          dom.hide(this._messageContainer);
          this._splitView = new SplitView(containerElement, { orientation: 1 /* HORIZONTAL */ });
          // editor
          this._previewContainer = dom.append(containerElement, dom.$('div.preview.inline'));
          let options = {
              scrollBeyondLastLine: false,
              scrollbar: {
                  verticalScrollbarSize: 14,
                  horizontal: 'auto',
                  useShadows: true,
                  verticalHasArrows: false,
                  horizontalHasArrows: false,
                  alwaysConsumeMouseWheel: false
              },
              overviewRulerLanes: 2,
              fixedOverflowWidgets: true,
              minimap: {
                  enabled: false
              }
          };
          this._preview = this._instantiationService.createInstance(EmbeddedCodeEditorWidget, this._previewContainer, options, this.editor);
          dom.hide(this._previewContainer);
          this._previewNotAvailableMessage = new TextModel(nls.localize('missingPreviewMessage', "no preview available"), TextModel.DEFAULT_CREATION_OPTIONS, null, null, this._undoRedoService, this._modeService, this._languageConfigurationService);
          // tree
          this._treeContainer = dom.append(containerElement, dom.$('div.ref-tree.inline'));
          const treeOptions = {
              keyboardSupport: this._defaultTreeKeyboardSupport,
              accessibilityProvider: new AccessibilityProvider(),
              keyboardNavigationLabelProvider: this._instantiationService.createInstance(StringRepresentationProvider),
              identityProvider: new IdentityProvider(),
              openOnSingleClick: true,
              selectionNavigation: true,
              overrideStyles: {
                  listBackground: peekView.peekViewResultsBackground
              }
          };
          if (this._defaultTreeKeyboardSupport) {
              // the tree will consume `Escape` and prevent the widget from closing
              this._callOnDispose.add(dom.addStandardDisposableListener(this._treeContainer, 'keydown', (e) => {
                  if (e.equals(9 /* Escape */)) {
                      this._keybindingService.dispatchEvent(e, e.target);
                      e.stopPropagation();
                  }
              }, true));
          }
          this._tree = this._instantiationService.createInstance(ReferencesTree, 'ReferencesWidget', this._treeContainer, new Delegate(), [
              this._instantiationService.createInstance(FileReferencesRenderer),
              this._instantiationService.createInstance(OneReferenceRenderer),
          ], this._instantiationService.createInstance(DataSource), treeOptions);
          // split stuff
          this._splitView.addView({
              onDidChange: Event.None,
              element: this._previewContainer,
              minimumSize: 200,
              maximumSize: Number.MAX_VALUE,
              layout: (width) => {
                  this._preview.layout({ height: this._dim.height, width });
              }
          }, Sizing.Distribute);
          this._splitView.addView({
              onDidChange: Event.None,
              element: this._treeContainer,
              minimumSize: 100,
              maximumSize: Number.MAX_VALUE,
              layout: (width) => {
                  this._treeContainer.style.height = `${this._dim.height}px`;
                  this._treeContainer.style.width = `${width}px`;
                  this._tree.layout(this._dim.height, width);
              }
          }, Sizing.Distribute);
          this._disposables.add(this._splitView.onDidSashChange(() => {
              if (this._dim.width) {
                  this.layoutData.ratio = this._splitView.getViewSize(0) / this._dim.width;
              }
          }, undefined));
          // listen on selection and focus
          let onEvent = (element, kind) => {
              if (element instanceof OneReference) {
                  if (kind === 'show') {
                      this._revealReference(element, false);
                  }
                  this._onDidSelectReference.fire({ element, kind, source: 'tree' });
              }
          };
          this._tree.onDidOpen(e => {
              if (e.sideBySide) {
                  onEvent(e.element, 'side');
              }
              else if (e.editorOptions.pinned) {
                  onEvent(e.element, 'goto');
              }
              else {
                  onEvent(e.element, 'show');
              }
          });
          dom.hide(this._treeContainer);
      }
      _onWidth(width) {
          if (this._dim) {
              this._doLayoutBody(this._dim.height, width);
          }
      }
      _doLayoutBody(heightInPixel, widthInPixel) {
          super._doLayoutBody(heightInPixel, widthInPixel);
          this._dim = new dom.Dimension(widthInPixel, heightInPixel);
          this.layoutData.heightInLines = this._viewZone ? this._viewZone.heightInLines : this.layoutData.heightInLines;
          this._splitView.layout(widthInPixel);
          this._splitView.resizeView(0, widthInPixel * this.layoutData.ratio);
      }
      setSelection(selection) {
          return this._revealReference(selection, true).then(() => {
              if (!this._model) {
                  // disposed
                  return;
              }
              // show in tree
              this._tree.setSelection([selection]);
              this._tree.setFocus([selection]);
          });
      }
      setModel(newModel) {
          // clean up
          this._disposeOnNewModel.clear();
          this._model = newModel;
          if (this._model) {
              return this._onNewModel();
          }
          return Promise.resolve();
      }
      _onNewModel() {
          if (!this._model) {
              return Promise.resolve(undefined);
          }
          if (this._model.isEmpty) {
              this.setTitle('');
              this._messageContainer.innerText = nls.localize('noResults', "No results");
              dom.show(this._messageContainer);
              return Promise.resolve(undefined);
          }
          dom.hide(this._messageContainer);
          this._decorationsManager = new DecorationsManager(this._preview, this._model);
          this._disposeOnNewModel.add(this._decorationsManager);
          // listen on model changes
          this._disposeOnNewModel.add(this._model.onDidChangeReferenceRange(reference => this._tree.rerender(reference)));
          // listen on editor
          this._disposeOnNewModel.add(this._preview.onMouseDown(e => {
              const { event, target } = e;
              if (event.detail !== 2) {
                  return;
              }
              const element = this._getFocusedReference();
              if (!element) {
                  return;
              }
              this._onDidSelectReference.fire({
                  element: { uri: element.uri, range: target.range },
                  kind: (event.ctrlKey || event.metaKey || event.altKey) ? 'side' : 'open',
                  source: 'editor'
              });
          }));
          // make sure things are rendered
          this.container.classList.add('results-loaded');
          dom.show(this._treeContainer);
          dom.show(this._previewContainer);
          this._splitView.layout(this._dim.width);
          this.focusOnReferenceTree();
          // pick input and a reference to begin with
          return this._tree.setInput(this._model.groups.length === 1 ? this._model.groups[0] : this._model);
      }
      _getFocusedReference() {
          const [element] = this._tree.getFocus();
          if (element instanceof OneReference) {
              return element;
          }
          else if (element instanceof FileReferences) {
              if (element.children.length > 0) {
                  return element.children[0];
              }
          }
          return undefined;
      }
      revealReference(reference) {
          return __awaiter(this, void 0, void 0, function* () {
              yield this._revealReference(reference, false);
              this._onDidSelectReference.fire({ element: reference, kind: 'goto', source: 'tree' });
          });
      }
      _revealReference(reference, revealParent) {
          return __awaiter(this, void 0, void 0, function* () {
              // check if there is anything to do...
              if (this._revealedReference === reference) {
                  return;
              }
              this._revealedReference = reference;
              // Update widget header
              if (reference.uri.scheme !== Schemas.inMemory) {
                  this.setTitle(basenameOrAuthority(reference.uri), this._uriLabel.getUriLabel(dirname(reference.uri)));
              }
              else {
                  this.setTitle(nls.localize('peekView.alternateTitle', "References"));
              }
              const promise = this._textModelResolverService.createModelReference(reference.uri);
              if (this._tree.getInput() === reference.parent) {
                  this._tree.reveal(reference);
              }
              else {
                  if (revealParent) {
                      this._tree.reveal(reference.parent);
                  }
                  yield this._tree.expand(reference.parent);
                  this._tree.reveal(reference);
              }
              const ref = yield promise;
              if (!this._model) {
                  // disposed
                  ref.dispose();
                  return;
              }
              dispose(this._previewModelReference);
              // show in editor
              const model = ref.object;
              if (model) {
                  const scrollType = this._preview.getModel() === model.textEditorModel ? 0 /* Smooth */ : 1 /* Immediate */;
                  const sel = Range.lift(reference.range).collapseToStart();
                  this._previewModelReference = ref;
                  this._preview.setModel(model.textEditorModel);
                  this._preview.setSelection(sel);
                  this._preview.revealRangeInCenter(sel, scrollType);
              }
              else {
                  this._preview.setModel(this._previewNotAvailableMessage);
                  ref.dispose();
              }
          });
      }
  };
  ReferenceWidget = __decorate([
      __param(3, IThemeService),
      __param(4, ITextModelService),
      __param(5, IInstantiationService),
      __param(6, peekView.IPeekViewService),
      __param(7, ILabelService),
      __param(8, IUndoRedoService),
      __param(9, IKeybindingService),
      __param(10, IModeService),
      __param(11, ILanguageConfigurationService)
  ], ReferenceWidget);
  export { ReferenceWidget };
  