"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const async = require("../../../../base/common/async.js");
const errors = require("../../../../base/common/errors.js");
const keyCodes = require("../../../../base/common/keyCodes.js");
const lifecycle = require("../../../../base/common/lifecycle.js");
const strings = require("../../../../base/common/strings.js");
const types = require("../../../../base/common/types.js");
require("./folding.css.js");
const stableEditorScroll = require("../../../browser/stableEditorScroll.js");
const editorExtensions = require("../../../browser/editorExtensions.js");
const editorContextKeys = require("../../../common/editorContextKeys.js");
const languages = require("../../../common/languages.js");
const languageConfigurationRegistry = require("../../../common/languages/languageConfigurationRegistry.js");
const foldingModel = require("./foldingModel.js");
const hiddenRangeModel = require("./hiddenRangeModel.js");
const indentRangeProvider = require("./indentRangeProvider.js");
const intializingRangeProvider = require("./intializingRangeProvider.js");
const nls = require("../../../../nls.js");
const contextkey = require("../../../../platform/contextkey/common/contextkey.js");
const colorRegistry = require("../../../../platform/theme/common/colorRegistry.js");
const themeService = require("../../../../platform/theme/common/themeService.js");
const foldingDecorations = require("./foldingDecorations.js");
const syntaxRangeProvider = require("./syntaxRangeProvider.js");
const notification = require("../../../../platform/notification/common/notification.js");
const severity = require("../../../../base/common/severity.js");
const languageFeatureDebounce = require("../../../common/services/languageFeatureDebounce.js");
const stopwatch = require("../../../../base/common/stopwatch.js");
const languageFeatures = require("../../../common/services/languageFeatures.js");
var __decorate = globalThis && globalThis.__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 = globalThis && globalThis.__param || function(paramIndex, decorator) {
  return function(target, key) {
    decorator(target, key, paramIndex);
  };
};
const CONTEXT_FOLDING_ENABLED = new contextkey.RawContextKey("foldingEnabled", false);
exports.FoldingController = class FoldingController extends lifecycle.Disposable {
  constructor(editor, contextKeyService, languageConfigurationService, notificationService, languageFeatureDebounceService, languageFeaturesService) {
    super();
    this.contextKeyService = contextKeyService;
    this.languageConfigurationService = languageConfigurationService;
    this.languageFeaturesService = languageFeaturesService;
    this._tooManyRegionsNotified = false;
    this.localToDispose = this._register(new lifecycle.DisposableStore());
    this.editor = editor;
    const options = this.editor.getOptions();
    this._isEnabled = options.get(
      37
      /* folding */
    );
    this._useFoldingProviders = options.get(
      38
      /* foldingStrategy */
    ) !== "indentation";
    this._unfoldOnClickAfterEndOfLine = options.get(
      42
      /* unfoldOnClickAfterEndOfLine */
    );
    this._restoringViewState = false;
    this._currentModelHasFoldedImports = false;
    this._foldingImportsByDefault = options.get(
      40
      /* foldingImportsByDefault */
    );
    this._maxFoldingRegions = options.get(
      41
      /* foldingMaximumRegions */
    );
    this.updateDebounceInfo = languageFeatureDebounceService.for(languageFeaturesService.foldingRangeProvider, "Folding", { min: 200 });
    this.foldingModel = null;
    this.hiddenRangeModel = null;
    this.rangeProvider = null;
    this.foldingRegionPromise = null;
    this.foldingStateMemento = null;
    this.foldingModelPromise = null;
    this.updateScheduler = null;
    this.cursorChangedScheduler = null;
    this.mouseDownInfo = null;
    this.foldingDecorationProvider = new foldingDecorations.FoldingDecorationProvider(editor);
    this.foldingDecorationProvider.autoHideFoldingControls = options.get(
      99
      /* showFoldingControls */
    ) === "mouseover";
    this.foldingDecorationProvider.showFoldingHighlights = options.get(
      39
      /* foldingHighlight */
    );
    this.foldingEnabled = CONTEXT_FOLDING_ENABLED.bindTo(this.contextKeyService);
    this.foldingEnabled.set(this._isEnabled);
    this._notifyTooManyRegions = (maxFoldingRegions) => {
      if (!this._tooManyRegionsNotified) {
        notificationService.notify({
          severity: severity.default.Warning,
          sticky: true,
          message: nls.localize("maximum fold ranges", `The number of foldable regions is limited to a maximum of {0}. Increase configuration option ['Folding Maximum Regions'](command:workbench.action.openSettings?["editor.foldingMaximumRegions"]) to enable more.`, maxFoldingRegions)
        });
        this._tooManyRegionsNotified = true;
      }
    };
    this._register(this.editor.onDidChangeModel(() => this.onModelChanged()));
    this._register(this.editor.onDidChangeConfiguration((e) => {
      if (e.hasChanged(
        37
        /* folding */
      )) {
        this._isEnabled = this.editor.getOptions().get(
          37
          /* folding */
        );
        this.foldingEnabled.set(this._isEnabled);
        this.onModelChanged();
      }
      if (e.hasChanged(
        41
        /* foldingMaximumRegions */
      )) {
        this._maxFoldingRegions = this.editor.getOptions().get(
          41
          /* foldingMaximumRegions */
        );
        this._tooManyRegionsNotified = false;
        this.onModelChanged();
      }
      if (e.hasChanged(
        99
        /* showFoldingControls */
      ) || e.hasChanged(
        39
        /* foldingHighlight */
      )) {
        const options2 = this.editor.getOptions();
        this.foldingDecorationProvider.autoHideFoldingControls = options2.get(
          99
          /* showFoldingControls */
        ) === "mouseover";
        this.foldingDecorationProvider.showFoldingHighlights = options2.get(
          39
          /* foldingHighlight */
        );
        this.triggerFoldingModelChanged();
      }
      if (e.hasChanged(
        38
        /* foldingStrategy */
      )) {
        this._useFoldingProviders = this.editor.getOptions().get(
          38
          /* foldingStrategy */
        ) !== "indentation";
        this.onFoldingStrategyChanged();
      }
      if (e.hasChanged(
        42
        /* unfoldOnClickAfterEndOfLine */
      )) {
        this._unfoldOnClickAfterEndOfLine = this.editor.getOptions().get(
          42
          /* unfoldOnClickAfterEndOfLine */
        );
      }
      if (e.hasChanged(
        40
        /* foldingImportsByDefault */
      )) {
        this._foldingImportsByDefault = this.editor.getOptions().get(
          40
          /* foldingImportsByDefault */
        );
      }
    }));
    this.onModelChanged();
  }
  static get(editor) {
    return editor.getContribution(FoldingController.ID);
  }
  /**
   * Store view state.
   */
  saveViewState() {
    let model = this.editor.getModel();
    if (!model || !this._isEnabled || model.isTooLargeForTokenization()) {
      return {};
    }
    if (this.foldingModel) {
      let collapsedRegions = this.foldingModel.isInitialized ? this.foldingModel.getMemento() : this.hiddenRangeModel.getMemento();
      let provider = this.rangeProvider ? this.rangeProvider.id : void 0;
      return { collapsedRegions, lineCount: model.getLineCount(), provider, foldedImports: this._currentModelHasFoldedImports };
    }
    return void 0;
  }
  /**
   * Restore view state.
   */
  restoreViewState(state) {
    let model = this.editor.getModel();
    if (!model || !this._isEnabled || model.isTooLargeForTokenization() || !this.hiddenRangeModel) {
      return;
    }
    if (!state || state.lineCount !== model.getLineCount()) {
      return;
    }
    this._currentModelHasFoldedImports = !!state.foldedImports;
    if (!state.collapsedRegions) {
      return;
    }
    if (state.provider === syntaxRangeProvider.ID_SYNTAX_PROVIDER || state.provider === intializingRangeProvider.ID_INIT_PROVIDER) {
      this.foldingStateMemento = state;
    }
    const collapsedRegions = state.collapsedRegions;
    if (this.hiddenRangeModel.applyMemento(collapsedRegions)) {
      const foldingModel2 = this.getFoldingModel();
      if (foldingModel2) {
        foldingModel2.then((foldingModel3) => {
          if (foldingModel3) {
            this._restoringViewState = true;
            try {
              foldingModel3.applyMemento(collapsedRegions);
            } finally {
              this._restoringViewState = false;
            }
          }
        }).then(void 0, errors.onUnexpectedError);
      }
    }
  }
  onModelChanged() {
    this.localToDispose.clear();
    let model = this.editor.getModel();
    if (!this._isEnabled || !model || model.isTooLargeForTokenization()) {
      return;
    }
    this._currentModelHasFoldedImports = false;
    this.foldingModel = new foldingModel.FoldingModel(model, this.foldingDecorationProvider);
    this.localToDispose.add(this.foldingModel);
    this.hiddenRangeModel = new hiddenRangeModel.HiddenRangeModel(this.foldingModel);
    this.localToDispose.add(this.hiddenRangeModel);
    this.localToDispose.add(this.hiddenRangeModel.onDidChange((hr) => this.onHiddenRangesChanges(hr)));
    this.updateScheduler = new async.Delayer(this.updateDebounceInfo.get(model));
    this.cursorChangedScheduler = new async.RunOnceScheduler(() => this.revealCursor(), 200);
    this.localToDispose.add(this.cursorChangedScheduler);
    this.localToDispose.add(this.languageFeaturesService.foldingRangeProvider.onDidChange(() => this.onFoldingStrategyChanged()));
    this.localToDispose.add(this.editor.onDidChangeModelLanguageConfiguration(() => this.onFoldingStrategyChanged()));
    this.localToDispose.add(this.editor.onDidChangeModelContent((e) => this.onDidChangeModelContent(e)));
    this.localToDispose.add(this.editor.onDidChangeCursorPosition(() => this.onCursorPositionChanged()));
    this.localToDispose.add(this.editor.onMouseDown((e) => this.onEditorMouseDown(e)));
    this.localToDispose.add(this.editor.onMouseUp((e) => this.onEditorMouseUp(e)));
    this.localToDispose.add({
      dispose: () => {
        if (this.foldingRegionPromise) {
          this.foldingRegionPromise.cancel();
          this.foldingRegionPromise = null;
        }
        if (this.updateScheduler) {
          this.updateScheduler.cancel();
        }
        this.updateScheduler = null;
        this.foldingModel = null;
        this.foldingModelPromise = null;
        this.hiddenRangeModel = null;
        this.cursorChangedScheduler = null;
        this.foldingStateMemento = null;
        if (this.rangeProvider) {
          this.rangeProvider.dispose();
        }
        this.rangeProvider = null;
      }
    });
    this.triggerFoldingModelChanged();
  }
  onFoldingStrategyChanged() {
    if (this.rangeProvider) {
      this.rangeProvider.dispose();
    }
    this.rangeProvider = null;
    this.triggerFoldingModelChanged();
  }
  getRangeProvider(editorModel) {
    if (this.rangeProvider) {
      return this.rangeProvider;
    }
    this.rangeProvider = new indentRangeProvider.IndentRangeProvider(editorModel, this.languageConfigurationService, this._maxFoldingRegions);
    if (this._useFoldingProviders && this.foldingModel) {
      let foldingProviders = this.languageFeaturesService.foldingRangeProvider.ordered(this.foldingModel.textModel);
      if (foldingProviders.length === 0 && this.foldingStateMemento && this.foldingStateMemento.collapsedRegions) {
        const rangeProvider = this.rangeProvider = new intializingRangeProvider.InitializingRangeProvider(editorModel, this.foldingStateMemento.collapsedRegions, () => {
          this.foldingStateMemento = null;
          this.onFoldingStrategyChanged();
        }, 3e4);
        return rangeProvider;
      } else if (foldingProviders.length > 0) {
        this.rangeProvider = new syntaxRangeProvider.SyntaxRangeProvider(editorModel, foldingProviders, () => this.triggerFoldingModelChanged(), this._maxFoldingRegions);
      }
    }
    this.foldingStateMemento = null;
    return this.rangeProvider;
  }
  getFoldingModel() {
    return this.foldingModelPromise;
  }
  onDidChangeModelContent(e) {
    var _a;
    (_a = this.hiddenRangeModel) === null || _a === void 0 ? void 0 : _a.notifyChangeModelContent(e);
    this.triggerFoldingModelChanged();
  }
  triggerFoldingModelChanged() {
    if (this.updateScheduler) {
      if (this.foldingRegionPromise) {
        this.foldingRegionPromise.cancel();
        this.foldingRegionPromise = null;
      }
      this.foldingModelPromise = this.updateScheduler.trigger(() => {
        const foldingModel2 = this.foldingModel;
        if (!foldingModel2) {
          return null;
        }
        const sw = new stopwatch.StopWatch(true);
        const provider = this.getRangeProvider(foldingModel2.textModel);
        let foldingRegionPromise = this.foldingRegionPromise = async.createCancelablePromise((token) => provider.compute(token, this._notifyTooManyRegions));
        return foldingRegionPromise.then((foldingRanges) => {
          if (foldingRanges && foldingRegionPromise === this.foldingRegionPromise) {
            let scrollState;
            if (this._foldingImportsByDefault && !this._currentModelHasFoldedImports) {
              const hasChanges = foldingRanges.setCollapsedAllOfType(languages.FoldingRangeKind.Imports.value, true);
              if (hasChanges) {
                scrollState = stableEditorScroll.StableEditorScrollState.capture(this.editor);
                this._currentModelHasFoldedImports = hasChanges;
              }
            }
            let selections = this.editor.getSelections();
            let selectionLineNumbers = selections ? selections.map((s) => s.startLineNumber) : [];
            foldingModel2.update(foldingRanges, selectionLineNumbers);
            if (scrollState) {
              scrollState.restore(this.editor);
            }
            const newValue = this.updateDebounceInfo.update(foldingModel2.textModel, sw.elapsed());
            if (this.updateScheduler) {
              this.updateScheduler.defaultDelay = newValue;
            }
          }
          return foldingModel2;
        });
      }).then(void 0, (err) => {
        errors.onUnexpectedError(err);
        return null;
      });
    }
  }
  onHiddenRangesChanges(hiddenRanges) {
    if (this.hiddenRangeModel && hiddenRanges.length && !this._restoringViewState) {
      let selections = this.editor.getSelections();
      if (selections) {
        if (this.hiddenRangeModel.adjustSelections(selections)) {
          this.editor.setSelections(selections);
        }
      }
    }
    this.editor.setHiddenAreas(hiddenRanges);
  }
  onCursorPositionChanged() {
    if (this.hiddenRangeModel && this.hiddenRangeModel.hasRanges()) {
      this.cursorChangedScheduler.schedule();
    }
  }
  revealCursor() {
    const foldingModel2 = this.getFoldingModel();
    if (!foldingModel2) {
      return;
    }
    foldingModel2.then((foldingModel3) => {
      if (foldingModel3) {
        let selections = this.editor.getSelections();
        if (selections && selections.length > 0) {
          let toToggle = [];
          for (let selection of selections) {
            let lineNumber = selection.selectionStartLineNumber;
            if (this.hiddenRangeModel && this.hiddenRangeModel.isHidden(lineNumber)) {
              toToggle.push(...foldingModel3.getAllRegionsAtLine(lineNumber, (r) => r.isCollapsed && lineNumber > r.startLineNumber));
            }
          }
          if (toToggle.length) {
            foldingModel3.toggleCollapseState(toToggle);
            this.reveal(selections[0].getPosition());
          }
        }
      }
    }).then(void 0, errors.onUnexpectedError);
  }
  onEditorMouseDown(e) {
    this.mouseDownInfo = null;
    if (!this.hiddenRangeModel || !e.target || !e.target.range) {
      return;
    }
    if (!e.event.leftButton && !e.event.middleButton) {
      return;
    }
    const range = e.target.range;
    let iconClicked = false;
    switch (e.target.type) {
      case 4: {
        const data = e.target.detail;
        const offsetLeftInGutter = e.target.element.offsetLeft;
        const gutterOffsetX = data.offsetX - offsetLeftInGutter;
        if (gutterOffsetX < 5) {
          return;
        }
        iconClicked = true;
        break;
      }
      case 7: {
        if (this._unfoldOnClickAfterEndOfLine && this.hiddenRangeModel.hasRanges()) {
          const data = e.target.detail;
          if (!data.isAfterLines) {
            break;
          }
        }
        return;
      }
      case 6: {
        if (this.hiddenRangeModel.hasRanges()) {
          let model = this.editor.getModel();
          if (model && range.startColumn === model.getLineMaxColumn(range.startLineNumber)) {
            break;
          }
        }
        return;
      }
      default:
        return;
    }
    this.mouseDownInfo = { lineNumber: range.startLineNumber, iconClicked };
  }
  onEditorMouseUp(e) {
    const foldingModel2 = this.getFoldingModel();
    if (!foldingModel2 || !this.mouseDownInfo || !e.target) {
      return;
    }
    let lineNumber = this.mouseDownInfo.lineNumber;
    let iconClicked = this.mouseDownInfo.iconClicked;
    let range = e.target.range;
    if (!range || range.startLineNumber !== lineNumber) {
      return;
    }
    if (iconClicked) {
      if (e.target.type !== 4) {
        return;
      }
    } else {
      let model = this.editor.getModel();
      if (!model || range.startColumn !== model.getLineMaxColumn(lineNumber)) {
        return;
      }
    }
    foldingModel2.then((foldingModel3) => {
      if (foldingModel3) {
        let region = foldingModel3.getRegionAtLine(lineNumber);
        if (region && region.startLineNumber === lineNumber) {
          let isCollapsed = region.isCollapsed;
          if (iconClicked || isCollapsed) {
            let surrounding = e.event.altKey;
            let toToggle = [];
            if (surrounding) {
              let filter = (otherRegion) => !otherRegion.containedBy(region) && !region.containedBy(otherRegion);
              let toMaybeToggle = foldingModel3.getRegionsInside(null, filter);
              for (const r of toMaybeToggle) {
                if (r.isCollapsed) {
                  toToggle.push(r);
                }
              }
              if (toToggle.length === 0) {
                toToggle = toMaybeToggle;
              }
            } else {
              let recursive = e.event.middleButton || e.event.shiftKey;
              if (recursive) {
                for (const r of foldingModel3.getRegionsInside(region)) {
                  if (r.isCollapsed === isCollapsed) {
                    toToggle.push(r);
                  }
                }
              }
              if (isCollapsed || !recursive || toToggle.length === 0) {
                toToggle.push(region);
              }
            }
            foldingModel3.toggleCollapseState(toToggle);
            this.reveal({ lineNumber, column: 1 });
          }
        }
      }
    }).then(void 0, errors.onUnexpectedError);
  }
  reveal(position) {
    this.editor.revealPositionInCenterIfOutsideViewport(
      position,
      0
      /* Smooth */
    );
  }
};
exports.FoldingController.ID = "editor.contrib.folding";
exports.FoldingController = __decorate([
  __param(1, contextkey.IContextKeyService),
  __param(2, languageConfigurationRegistry.ILanguageConfigurationService),
  __param(3, notification.INotificationService),
  __param(4, languageFeatureDebounce.ILanguageFeatureDebounceService),
  __param(5, languageFeatures.ILanguageFeaturesService)
], exports.FoldingController);
class FoldingAction extends editorExtensions.EditorAction {
  runEditorCommand(accessor, editor, args) {
    const languageConfigurationService = accessor.get(languageConfigurationRegistry.ILanguageConfigurationService);
    const foldingController = exports.FoldingController.get(editor);
    if (!foldingController) {
      return;
    }
    const foldingModelPromise = foldingController.getFoldingModel();
    if (foldingModelPromise) {
      this.reportTelemetry(accessor, editor);
      return foldingModelPromise.then((foldingModel2) => {
        if (foldingModel2) {
          this.invoke(foldingController, foldingModel2, editor, args, languageConfigurationService);
          const selection = editor.getSelection();
          if (selection) {
            foldingController.reveal(selection.getStartPosition());
          }
        }
      });
    }
  }
  getSelectedLines(editor) {
    let selections = editor.getSelections();
    return selections ? selections.map((s) => s.startLineNumber) : [];
  }
  getLineNumbers(args, editor) {
    if (args && args.selectionLines) {
      return args.selectionLines.map((l) => l + 1);
    }
    return this.getSelectedLines(editor);
  }
  run(_accessor, _editor) {
  }
}
function foldingArgumentsConstraint(args) {
  if (!types.isUndefined(args)) {
    if (!types.isObject(args)) {
      return false;
    }
    const foldingArgs = args;
    if (!types.isUndefined(foldingArgs.levels) && !types.isNumber(foldingArgs.levels)) {
      return false;
    }
    if (!types.isUndefined(foldingArgs.direction) && !types.isString(foldingArgs.direction)) {
      return false;
    }
    if (!types.isUndefined(foldingArgs.selectionLines) && (!types.isArray(foldingArgs.selectionLines) || !foldingArgs.selectionLines.every(types.isNumber))) {
      return false;
    }
  }
  return true;
}
class UnfoldAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.unfold",
      label: nls.localize("unfoldAction.label", "Unfold"),
      alias: "Unfold",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: 2048 | 1024 | 89,
        mac: {
          primary: 2048 | 512 | 89
          /* BracketRight */
        },
        weight: 100
        /* EditorContrib */
      },
      description: {
        description: "Unfold the content in the editor",
        args: [
          {
            name: "Unfold editor argument",
            description: `Property-value pairs that can be passed through this argument:
						* 'levels': Number of levels to unfold. If not set, defaults to 1.
						* 'direction': If 'up', unfold given number of levels up otherwise unfolds down.
						* 'selectionLines': The start lines (0-based) of the editor selections to apply the unfold action to. If not set, the active selection(s) will be used.
						`,
            constraint: foldingArgumentsConstraint,
            schema: {
              "type": "object",
              "properties": {
                "levels": {
                  "type": "number",
                  "default": 1
                },
                "direction": {
                  "type": "string",
                  "enum": ["up", "down"],
                  "default": "down"
                },
                "selectionLines": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              }
            }
          }
        ]
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor, args) {
    let levels = args && args.levels || 1;
    let lineNumbers = this.getLineNumbers(args, editor);
    if (args && args.direction === "up") {
      foldingModel.setCollapseStateLevelsUp(foldingModel$1, false, levels, lineNumbers);
    } else {
      foldingModel.setCollapseStateLevelsDown(foldingModel$1, false, levels, lineNumbers);
    }
  }
}
class UnFoldRecursivelyAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.unfoldRecursively",
      label: nls.localize("unFoldRecursivelyAction.label", "Unfold Recursively"),
      alias: "Unfold Recursively",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 89
          /* BracketRight */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor, _args) {
    foldingModel.setCollapseStateLevelsDown(foldingModel$1, false, Number.MAX_VALUE, this.getSelectedLines(editor));
  }
}
class FoldAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.fold",
      label: nls.localize("foldAction.label", "Fold"),
      alias: "Fold",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: 2048 | 1024 | 87,
        mac: {
          primary: 2048 | 512 | 87
          /* BracketLeft */
        },
        weight: 100
        /* EditorContrib */
      },
      description: {
        description: "Fold the content in the editor",
        args: [
          {
            name: "Fold editor argument",
            description: `Property-value pairs that can be passed through this argument:
							* 'levels': Number of levels to fold.
							* 'direction': If 'up', folds given number of levels up otherwise folds down.
							* 'selectionLines': The start lines (0-based) of the editor selections to apply the fold action to. If not set, the active selection(s) will be used.
							If no levels or direction is set, folds the region at the locations or if already collapsed, the first uncollapsed parent instead.
						`,
            constraint: foldingArgumentsConstraint,
            schema: {
              "type": "object",
              "properties": {
                "levels": {
                  "type": "number"
                },
                "direction": {
                  "type": "string",
                  "enum": ["up", "down"]
                },
                "selectionLines": {
                  "type": "array",
                  "items": {
                    "type": "number"
                  }
                }
              }
            }
          }
        ]
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor, args) {
    let lineNumbers = this.getLineNumbers(args, editor);
    const levels = args && args.levels;
    const direction = args && args.direction;
    if (typeof levels !== "number" && typeof direction !== "string") {
      foldingModel.setCollapseStateUp(foldingModel$1, true, lineNumbers);
    } else {
      if (direction === "up") {
        foldingModel.setCollapseStateLevelsUp(foldingModel$1, true, levels || 1, lineNumbers);
      } else {
        foldingModel.setCollapseStateLevelsDown(foldingModel$1, true, levels || 1, lineNumbers);
      }
    }
  }
}
class ToggleFoldAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.toggleFold",
      label: nls.localize("toggleFoldAction.label", "Toggle Fold"),
      alias: "Toggle Fold",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 42
          /* KeyL */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor) {
    let selectedLines = this.getSelectedLines(editor);
    foldingModel.toggleCollapseState(foldingModel$1, 1, selectedLines);
  }
}
class FoldRecursivelyAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.foldRecursively",
      label: nls.localize("foldRecursivelyAction.label", "Fold Recursively"),
      alias: "Fold Recursively",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 87
          /* BracketLeft */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor) {
    let selectedLines = this.getSelectedLines(editor);
    foldingModel.setCollapseStateLevelsDown(foldingModel$1, true, Number.MAX_VALUE, selectedLines);
  }
}
class FoldAllBlockCommentsAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.foldAllBlockComments",
      label: nls.localize("foldAllBlockComments.label", "Fold All Block Comments"),
      alias: "Fold All Block Comments",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 85
          /* Slash */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor, args, languageConfigurationService) {
    if (foldingModel$1.regions.hasTypes()) {
      foldingModel.setCollapseStateForType(foldingModel$1, languages.FoldingRangeKind.Comment.value, true);
    } else {
      const editorModel = editor.getModel();
      if (!editorModel) {
        return;
      }
      const comments = languageConfigurationService.getLanguageConfiguration(editorModel.getLanguageId()).comments;
      if (comments && comments.blockCommentStartToken) {
        let regExp = new RegExp("^\\s*" + strings.escapeRegExpCharacters(comments.blockCommentStartToken));
        foldingModel.setCollapseStateForMatchingLines(foldingModel$1, regExp, true);
      }
    }
  }
}
class FoldAllRegionsAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.foldAllMarkerRegions",
      label: nls.localize("foldAllMarkerRegions.label", "Fold All Regions"),
      alias: "Fold All Regions",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 29
          /* Digit8 */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor, args, languageConfigurationService) {
    if (foldingModel$1.regions.hasTypes()) {
      foldingModel.setCollapseStateForType(foldingModel$1, languages.FoldingRangeKind.Region.value, true);
    } else {
      const editorModel = editor.getModel();
      if (!editorModel) {
        return;
      }
      const foldingRules = languageConfigurationService.getLanguageConfiguration(editorModel.getLanguageId()).foldingRules;
      if (foldingRules && foldingRules.markers && foldingRules.markers.start) {
        let regExp = new RegExp(foldingRules.markers.start);
        foldingModel.setCollapseStateForMatchingLines(foldingModel$1, regExp, true);
      }
    }
  }
}
class UnfoldAllRegionsAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.unfoldAllMarkerRegions",
      label: nls.localize("unfoldAllMarkerRegions.label", "Unfold All Regions"),
      alias: "Unfold All Regions",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 30
          /* Digit9 */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor, args, languageConfigurationService) {
    if (foldingModel$1.regions.hasTypes()) {
      foldingModel.setCollapseStateForType(foldingModel$1, languages.FoldingRangeKind.Region.value, false);
    } else {
      const editorModel = editor.getModel();
      if (!editorModel) {
        return;
      }
      const foldingRules = languageConfigurationService.getLanguageConfiguration(editorModel.getLanguageId()).foldingRules;
      if (foldingRules && foldingRules.markers && foldingRules.markers.start) {
        let regExp = new RegExp(foldingRules.markers.start);
        foldingModel.setCollapseStateForMatchingLines(foldingModel$1, regExp, false);
      }
    }
  }
}
class FoldAllRegionsExceptAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.foldAllExcept",
      label: nls.localize("foldAllExcept.label", "Fold All Regions Except Selected"),
      alias: "Fold All Regions Except Selected",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 83
          /* Minus */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor) {
    let selectedLines = this.getSelectedLines(editor);
    foldingModel.setCollapseStateForRest(foldingModel$1, true, selectedLines);
  }
}
class UnfoldAllRegionsExceptAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.unfoldAllExcept",
      label: nls.localize("unfoldAllExcept.label", "Unfold All Regions Except Selected"),
      alias: "Unfold All Regions Except Selected",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 81
          /* Equal */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor) {
    let selectedLines = this.getSelectedLines(editor);
    foldingModel.setCollapseStateForRest(foldingModel$1, false, selectedLines);
  }
}
class FoldAllAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.foldAll",
      label: nls.localize("foldAllAction.label", "Fold All"),
      alias: "Fold All",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 21
          /* Digit0 */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, _editor) {
    foldingModel.setCollapseStateLevelsDown(foldingModel$1, true);
  }
}
class UnfoldAllAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.unfoldAll",
      label: nls.localize("unfoldAllAction.label", "Unfold All"),
      alias: "Unfold All",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        primary: keyCodes.KeyChord(
          2048 | 41,
          2048 | 40
          /* KeyJ */
        ),
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, _editor) {
    foldingModel.setCollapseStateLevelsDown(foldingModel$1, false);
  }
}
class FoldLevelAction extends FoldingAction {
  getFoldingLevel() {
    return parseInt(this.id.substr(FoldLevelAction.ID_PREFIX.length));
  }
  invoke(_foldingController, foldingModel$1, editor) {
    foldingModel.setCollapseStateAtLevel(foldingModel$1, this.getFoldingLevel(), true, this.getSelectedLines(editor));
  }
}
FoldLevelAction.ID_PREFIX = "editor.foldLevel";
FoldLevelAction.ID = (level) => FoldLevelAction.ID_PREFIX + level;
class GotoParentFoldAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.gotoParentFold",
      label: nls.localize("gotoParentFold.label", "Go to Parent Fold"),
      alias: "Go to Parent Fold",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor) {
    let selectedLines = this.getSelectedLines(editor);
    if (selectedLines.length > 0) {
      let startLineNumber = foldingModel.getParentFoldLine(selectedLines[0], foldingModel$1);
      if (startLineNumber !== null) {
        editor.setSelection({
          startLineNumber,
          startColumn: 1,
          endLineNumber: startLineNumber,
          endColumn: 1
        });
      }
    }
  }
}
class GotoPreviousFoldAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.gotoPreviousFold",
      label: nls.localize("gotoPreviousFold.label", "Go to Previous Folding Range"),
      alias: "Go to Previous Folding Range",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor) {
    let selectedLines = this.getSelectedLines(editor);
    if (selectedLines.length > 0) {
      let startLineNumber = foldingModel.getPreviousFoldLine(selectedLines[0], foldingModel$1);
      if (startLineNumber !== null) {
        editor.setSelection({
          startLineNumber,
          startColumn: 1,
          endLineNumber: startLineNumber,
          endColumn: 1
        });
      }
    }
  }
}
class GotoNextFoldAction extends FoldingAction {
  constructor() {
    super({
      id: "editor.gotoNextFold",
      label: nls.localize("gotoNextFold.label", "Go to Next Folding Range"),
      alias: "Go to Next Folding Range",
      precondition: CONTEXT_FOLDING_ENABLED,
      kbOpts: {
        kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
        weight: 100
        /* EditorContrib */
      }
    });
  }
  invoke(_foldingController, foldingModel$1, editor) {
    let selectedLines = this.getSelectedLines(editor);
    if (selectedLines.length > 0) {
      let startLineNumber = foldingModel.getNextFoldLine(selectedLines[0], foldingModel$1);
      if (startLineNumber !== null) {
        editor.setSelection({
          startLineNumber,
          startColumn: 1,
          endLineNumber: startLineNumber,
          endColumn: 1
        });
      }
    }
  }
}
editorExtensions.registerEditorContribution(exports.FoldingController.ID, exports.FoldingController);
editorExtensions.registerEditorAction(UnfoldAction);
editorExtensions.registerEditorAction(UnFoldRecursivelyAction);
editorExtensions.registerEditorAction(FoldAction);
editorExtensions.registerEditorAction(FoldRecursivelyAction);
editorExtensions.registerEditorAction(FoldAllAction);
editorExtensions.registerEditorAction(UnfoldAllAction);
editorExtensions.registerEditorAction(FoldAllBlockCommentsAction);
editorExtensions.registerEditorAction(FoldAllRegionsAction);
editorExtensions.registerEditorAction(UnfoldAllRegionsAction);
editorExtensions.registerEditorAction(FoldAllRegionsExceptAction);
editorExtensions.registerEditorAction(UnfoldAllRegionsExceptAction);
editorExtensions.registerEditorAction(ToggleFoldAction);
editorExtensions.registerEditorAction(GotoParentFoldAction);
editorExtensions.registerEditorAction(GotoPreviousFoldAction);
editorExtensions.registerEditorAction(GotoNextFoldAction);
for (let i = 1; i <= 7; i++) {
  editorExtensions.registerInstantiatedEditorAction(new FoldLevelAction({
    id: FoldLevelAction.ID(i),
    label: nls.localize("foldLevelAction.label", "Fold Level {0}", i),
    alias: `Fold Level ${i}`,
    precondition: CONTEXT_FOLDING_ENABLED,
    kbOpts: {
      kbExpr: editorContextKeys.EditorContextKeys.editorTextFocus,
      primary: keyCodes.KeyChord(2048 | 41, 2048 | 21 + i),
      weight: 100
      /* EditorContrib */
    }
  }));
}
const foldBackgroundBackground = colorRegistry.registerColor("editor.foldBackground", { light: colorRegistry.transparent(colorRegistry.editorSelectionBackground, 0.3), dark: colorRegistry.transparent(colorRegistry.editorSelectionBackground, 0.3), hc: null }, nls.localize("foldBackgroundBackground", "Background color behind folded ranges. The color must not be opaque so as not to hide underlying decorations."), true);
const editorFoldForeground = colorRegistry.registerColor("editorGutter.foldingControlForeground", { dark: colorRegistry.iconForeground, light: colorRegistry.iconForeground, hc: colorRegistry.iconForeground }, nls.localize("editorGutter.foldingControlForeground", "Color of the folding control in the editor gutter."));
themeService.registerThemingParticipant((theme, collector) => {
  const foldBackground = theme.getColor(foldBackgroundBackground);
  if (foldBackground) {
    collector.addRule(`.monaco-editor .folded-background { background-color: ${foldBackground}; }`);
  }
  const editorFoldColor = theme.getColor(editorFoldForeground);
  if (editorFoldColor) {
    collector.addRule(`
		.monaco-editor .cldr${themeService.ThemeIcon.asCSSSelector(foldingDecorations.foldingExpandedIcon)},
		.monaco-editor .cldr${themeService.ThemeIcon.asCSSSelector(foldingDecorations.foldingCollapsedIcon)} {
			color: ${editorFoldColor} !important;
		}
		`);
  }
});
exports.editorFoldForeground = editorFoldForeground;
exports.foldBackgroundBackground = foldBackgroundBackground;
