From cd21d906ca9db4984ff6c698ea31f07af3dc11dc Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Fri, 23 Feb 2018 08:30:56 +0100 Subject: [PATCH] [folding] fold comments / region --- src/vs/editor/contrib/folding/folding.ts | 40 ++++++++++++------- src/vs/editor/contrib/folding/foldingModel.ts | 15 +++++++ .../editor/contrib/folding/foldingRanges.ts | 12 +++++- .../contrib/folding/syntaxRangeProvider.ts | 17 +++++--- .../api/node/extHostTypeConverters.ts | 2 +- src/vs/workbench/api/node/extHostTypes.ts | 4 +- 6 files changed, 66 insertions(+), 24 deletions(-) diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index 2eaa4756dba..459f83d973c 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -17,7 +17,7 @@ import { ScrollType, IEditorContribution } from 'vs/editor/common/editorCommon'; import { ITextModel } from 'vs/editor/common/model'; import { registerEditorAction, registerEditorContribution, ServicesAccessor, EditorAction, registerInstantiatedEditorAction } from 'vs/editor/browser/editorExtensions'; import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; -import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines } from 'vs/editor/contrib/folding/foldingModel'; +import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType } from 'vs/editor/contrib/folding/foldingModel'; import { FoldingDecorationProvider } from './foldingDecorations'; import { FoldingRegions } from './foldingRanges'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; @@ -28,7 +28,7 @@ import { IRange } from 'vs/editor/common/core/range'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { IndentRangeProvider } from 'vs/editor/contrib/folding/indentRangeProvider'; import { IPosition } from 'vs/editor/common/core/position'; -import { FoldingProviderRegistry } from 'vs/editor/common/modes'; +import { FoldingProviderRegistry, FoldingRangeType } from 'vs/editor/common/modes'; import { SyntaxRangeProvider } from './syntaxRangeProvider'; export const ID = 'editor.contrib.folding'; @@ -553,10 +553,14 @@ class FoldAllBlockCommentsAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void { - let comments = LanguageConfigurationRegistry.getComments(editor.getModel().getLanguageIdentifier().id); - if (comments && comments.blockCommentStartToken) { - let regExp = new RegExp('^\\s*' + escapeRegExpCharacters(comments.blockCommentStartToken)); - setCollapseStateForMatchingLines(foldingModel, regExp, true); + if (foldingModel.regions.hasTypes()) { + setCollapseStateForType(foldingModel, FoldingRangeType.Comment, true); + } else { + let comments = LanguageConfigurationRegistry.getComments(editor.getModel().getLanguageIdentifier().id); + if (comments && comments.blockCommentStartToken) { + let regExp = new RegExp('^\\s*' + escapeRegExpCharacters(comments.blockCommentStartToken)); + setCollapseStateForMatchingLines(foldingModel, regExp, true); + } } } } @@ -577,10 +581,14 @@ class FoldAllRegionsAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void { - let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); - if (foldingRules && foldingRules.markers && foldingRules.markers.start) { - let regExp = new RegExp(foldingRules.markers.start); - setCollapseStateForMatchingLines(foldingModel, regExp, true); + if (foldingModel.regions.hasTypes()) { + setCollapseStateForType(foldingModel, FoldingRangeType.Region, true); + } else { + let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); + if (foldingRules && foldingRules.markers && foldingRules.markers.start) { + let regExp = new RegExp(foldingRules.markers.start); + setCollapseStateForMatchingLines(foldingModel, regExp, true); + } } } } @@ -601,10 +609,14 @@ class UnfoldAllRegionsAction extends FoldingAction { } invoke(foldingController: FoldingController, foldingModel: FoldingModel, editor: ICodeEditor): void { - let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); - if (foldingRules && foldingRules.markers && foldingRules.markers.start) { - let regExp = new RegExp(foldingRules.markers.start); - setCollapseStateForMatchingLines(foldingModel, regExp, false); + if (foldingModel.regions.hasTypes()) { + setCollapseStateForType(foldingModel, FoldingRangeType.Region, false); + } else { + let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); + if (foldingRules && foldingRules.markers && foldingRules.markers.start) { + let regExp = new RegExp(foldingRules.markers.start); + setCollapseStateForMatchingLines(foldingModel, regExp, false); + } } } } diff --git a/src/vs/editor/contrib/folding/foldingModel.ts b/src/vs/editor/contrib/folding/foldingModel.ts index 5fbb9f2289a..304df786969 100644 --- a/src/vs/editor/contrib/folding/foldingModel.ts +++ b/src/vs/editor/contrib/folding/foldingModel.ts @@ -308,3 +308,18 @@ export function setCollapseStateForMatchingLines(foldingModel: FoldingModel, reg } foldingModel.toggleCollapseState(toToggle); } + +/** + * Folds all regions of the given type + * @param foldingModel the folding model + */ +export function setCollapseStateForType(foldingModel: FoldingModel, type: string, doCollapse: boolean): void { + let regions = foldingModel.regions; + let toToggle = []; + for (let i = regions.length - 1; i >= 0; i--) { + if (doCollapse !== regions.isCollapsed(i) && type === regions.getType(i)) { + toToggle.push(regions.toRegion(i)); + } + } + foldingModel.toggleCollapseState(toToggle); +} diff --git a/src/vs/editor/contrib/folding/foldingRanges.ts b/src/vs/editor/contrib/folding/foldingRanges.ts index 613fe4c169b..8be1a9aad17 100644 --- a/src/vs/editor/contrib/folding/foldingRanges.ts +++ b/src/vs/editor/contrib/folding/foldingRanges.ts @@ -20,14 +20,16 @@ export class FoldingRegions { private _endIndexes: Uint32Array; private _collapseStates: Uint32Array; private _parentsComputed: boolean; + private _types: string[] | undefined; - constructor(startIndexes: Uint32Array, endIndexes: Uint32Array) { + constructor(startIndexes: Uint32Array, endIndexes: Uint32Array, types?: string[]) { if (startIndexes.length !== endIndexes.length || startIndexes.length > MAX_FOLDING_REGIONS) { throw new Error('invalid startIndexes or endIndexes size'); } this._startIndexes = startIndexes; this._endIndexes = endIndexes; this._collapseStates = new Uint32Array(Math.ceil(startIndexes.length / 32)); + this._types = types; } private ensureParentIndices() { @@ -67,6 +69,14 @@ export class FoldingRegions { return this._endIndexes[index] & MAX_LINE_NUMBER; } + public getType(index: number): string | undefined { + return this._types ? this._types[index] : void 0; + } + + public hasTypes() { + return !!this._types; + } + public isCollapsed(index: number): boolean { let arrayIndex = (index / 32) | 0; let bit = index % 32; diff --git a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts index 345f08a12f3..fbb76d270f4 100644 --- a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts +++ b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts @@ -52,6 +52,7 @@ export class RangesCollector { private _endIndexes: number[]; private _nestingLevels: number[]; private _nestingLevelCounts: number[]; + private _types: string[]; private _length: number; private _foldingRangesLimit: number; @@ -60,11 +61,12 @@ export class RangesCollector { this._endIndexes = []; this._nestingLevels = []; this._nestingLevelCounts = []; + this._types = []; this._length = 0; this._foldingRangesLimit = foldingRangesLimit; } - public add(startLineNumber: number, endLineNumber: number, nestingLevel: number) { + public add(startLineNumber: number, endLineNumber: number, type: string, nestingLevel: number) { if (startLineNumber > MAX_LINE_NUMBER || endLineNumber > MAX_LINE_NUMBER) { return; } @@ -72,6 +74,7 @@ export class RangesCollector { this._startIndexes[index] = startLineNumber; this._endIndexes[index] = endLineNumber; this._nestingLevels[index] = nestingLevel; + this._types[index] = type; this._length++; if (nestingLevel < 30) { this._nestingLevelCounts[nestingLevel] = (this._nestingLevelCounts[nestingLevel] || 0) + 1; @@ -86,7 +89,7 @@ export class RangesCollector { startIndexes[i] = this._startIndexes[i]; endIndexes[i] = this._endIndexes[i]; } - return new FoldingRegions(startIndexes, endIndexes); + return new FoldingRegions(startIndexes, endIndexes, this._types); } else { let entries = 0; let maxLevel = this._nestingLevelCounts.length; @@ -102,15 +105,17 @@ export class RangesCollector { } let startIndexes = new Uint32Array(entries); let endIndexes = new Uint32Array(entries); + let types = []; for (let i = 0, k = 0; i < this._length; i++) { let level = this._nestingLevels[i]; if (level < maxLevel) { startIndexes[k] = this._startIndexes[i]; endIndexes[k] = this._endIndexes[i]; + types[k] = this._types[i]; k++; } } - return new FoldingRegions(startIndexes, endIndexes); + return new FoldingRegions(startIndexes, endIndexes, types); } } @@ -132,20 +137,20 @@ export function sanitizeRanges(rangeData: IFoldingRangeData[]): FoldingRegions { for (let entry of sorted) { if (!top) { top = entry; - collector.add(entry.startLineNumber, entry.endLineNumber, previous.length); + collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length); } else { if (entry.startLineNumber > top.startLineNumber) { if (entry.endLineNumber <= top.endLineNumber) { previous.push(top); top = entry; - collector.add(entry.startLineNumber, entry.endLineNumber, previous.length); + collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length); } else if (entry.startLineNumber > top.endLineNumber) { do { top = previous.pop(); } while (top && entry.startLineNumber > top.endLineNumber); previous.push(top); top = entry; - collector.add(entry.startLineNumber, entry.endLineNumber, previous.length); + collector.add(entry.startLineNumber, entry.endLineNumber, entry.type, previous.length); } } } diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index c15538d7339..e8a7a571bc6 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -589,7 +589,7 @@ export namespace ProgressLocation { export namespace FoldingRangeList { export function from(rangeList: vscode.FoldingRangeList): modes.IFoldingRangeList { return { - ranges: rangeList.ranges.map(r => ({ startLineNumber: r.startLine + 1, endLineNumber: r.endLine + 1 })) + ranges: rangeList.ranges.map(r => ({ startLineNumber: r.startLine + 1, endLineNumber: r.endLine + 1, type: r.type })) }; } } diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 41bf5746751..c00cf7b2703 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -1677,9 +1677,9 @@ export class FoldingRange { endLine: number; - type?: FoldingRangeType; + type?: FoldingRangeType | string; - constructor(startLine: number, endLine: number, type?: FoldingRangeType) { + constructor(startLine: number, endLine: number, type?: FoldingRangeType | string) { this.startLine = startLine; this.endLine = endLine; this.type = type;