diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index a1023ddb0fd..94b6e470c81 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -284,6 +284,20 @@ "./vs/editor/contrib/find/findState.ts", "./vs/editor/contrib/find/replaceAllCommand.ts", "./vs/editor/contrib/find/replacePattern.ts", + "./vs/editor/contrib/folding/folding.ts", + "./vs/editor/contrib/folding/foldingDecorations.ts", + "./vs/editor/contrib/folding/foldingModel.ts", + "./vs/editor/contrib/folding/foldingRanges.ts", + "./vs/editor/contrib/folding/hiddenRangeModel.ts", + "./vs/editor/contrib/folding/indentRangeProvider.ts", + "./vs/editor/contrib/folding/intializingRangeProvider.ts", + "./vs/editor/contrib/folding/syntaxRangeProvider.ts", + "./vs/editor/contrib/folding/test/syntaxFold.test.ts", + "./vs/editor/contrib/folding/test/indentRangeProvider.test.ts", + "./vs/editor/contrib/folding/test/indentFold.test.ts", + "./vs/editor/contrib/folding/test/hiddenRangeModel.test.ts", + "./vs/editor/contrib/folding/test/foldingRanges.test.ts", + "./vs/editor/contrib/folding/test/foldingModel.test.ts", "./vs/editor/contrib/fontZoom/fontZoom.ts", "./vs/editor/contrib/goToDefinition/clickLinkGesture.ts", "./vs/editor/contrib/hover/getHover.ts", diff --git a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts index 93ef5e0ad7c..09e4d6b319e 100644 --- a/src/vs/editor/contrib/bracketMatching/bracketMatching.ts +++ b/src/vs/editor/contrib/bracketMatching/bracketMatching.ts @@ -188,7 +188,6 @@ export class BracketMatchingController extends Disposable implements editorCommo this._editor.getSelections().forEach(selection => { const position = selection.getStartPosition(); - let brackets = model.matchBracket(position); let openBracket: Position | null = null; diff --git a/src/vs/editor/contrib/folding/folding.ts b/src/vs/editor/contrib/folding/folding.ts index 297f17cff86..5035b697113 100644 --- a/src/vs/editor/contrib/folding/folding.ts +++ b/src/vs/editor/contrib/folding/folding.ts @@ -16,7 +16,7 @@ import { registerEditorAction, registerEditorContribution, ServicesAccessor, Edi import { ICodeEditor, IEditorMouseEvent, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { FoldingModel, setCollapseStateAtLevel, CollapseMemento, setCollapseStateLevelsDown, setCollapseStateLevelsUp, setCollapseStateForMatchingLines, setCollapseStateForType } from 'vs/editor/contrib/folding/foldingModel'; import { FoldingDecorationProvider } from './foldingDecorations'; -import { FoldingRegions } from './foldingRanges'; +import { FoldingRegions, FoldingRegion } from './foldingRanges'; import { EditorContextKeys } from 'vs/editor/common/editorContextKeys'; import { IConfigurationChangedEvent } from 'vs/editor/common/config/editorOptions'; import { IMarginData, IEmptyContentData } from 'vs/editor/browser/controller/mouseTarget'; @@ -36,7 +36,7 @@ export const ID = 'editor.contrib.folding'; export interface RangeProvider { readonly id: string; - compute(cancelationToken: CancellationToken): Thenable; + compute(cancelationToken: CancellationToken): Thenable; dispose(): void; } @@ -62,20 +62,20 @@ export class FoldingController implements IEditorContribution { private foldingDecorationProvider: FoldingDecorationProvider; - private foldingModel: FoldingModel; - private hiddenRangeModel: HiddenRangeModel; + private foldingModel: FoldingModel | null; + private hiddenRangeModel: HiddenRangeModel | null; - private rangeProvider: RangeProvider; - private foldingRegionPromise: CancelablePromise; + private rangeProvider: RangeProvider | null; + private foldingRegionPromise: CancelablePromise | null; - private foldingStateMemento: FoldingStateMemento; + private foldingStateMemento: FoldingStateMemento | null; - private foldingModelPromise: Thenable; - private updateScheduler: Delayer; + private foldingModelPromise: Thenable | null; + private updateScheduler: Delayer | null; private globalToDispose: IDisposable[]; - private cursorChangedScheduler: RunOnceScheduler; + private cursorChangedScheduler: RunOnceScheduler | null; private localToDispose: IDisposable[]; @@ -129,13 +129,13 @@ export class FoldingController implements IEditorContribution { /** * Store view state. */ - public saveViewState(): FoldingStateMemento { + public saveViewState(): FoldingStateMemento | undefined { let model = this.editor.getModel(); if (!model || !this._isEnabled || model.isTooLargeForTokenization()) { return {}; } if (this.foldingModel) { // disposed ? - let collapsedRegions = this.foldingModel.isInitialized ? this.foldingModel.getMemento() : this.hiddenRangeModel.getMemento(); + 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 }; } @@ -147,7 +147,7 @@ export class FoldingController implements IEditorContribution { */ public restoreViewState(state: FoldingStateMemento): void { let model = this.editor.getModel(); - if (!model || !this._isEnabled || model.isTooLargeForTokenization()) { + if (!model || !this._isEnabled || model.isTooLargeForTokenization() || !this.hiddenRangeModel) { return; } if (!state || !state.collapsedRegions || state.lineCount !== model.getLineCount()) { @@ -158,13 +158,18 @@ export class FoldingController implements IEditorContribution { this.foldingStateMemento = state; } + const collapsedRegions = state.collapsedRegions; + // set the hidden ranges right away, before waiting for the folding model. - if (this.hiddenRangeModel.applyMemento(state.collapsedRegions)) { - this.getFoldingModel().then(foldingModel => { - if (foldingModel) { - foldingModel.applyMemento(state.collapsedRegions); - } - }).then(undefined, onUnexpectedError); + if (this.hiddenRangeModel.applyMemento(collapsedRegions)) { + const foldingModel = this.getFoldingModel(); + if (foldingModel) { + foldingModel.then(foldingModel => { + if (foldingModel) { + foldingModel.applyMemento(collapsedRegions); + } + }).then(undefined, onUnexpectedError); + } } } @@ -199,7 +204,9 @@ export class FoldingController implements IEditorContribution { this.foldingRegionPromise.cancel(); this.foldingRegionPromise = null; } - this.updateScheduler.cancel(); + if (this.updateScheduler) { + this.updateScheduler.cancel(); + } this.updateScheduler = null; this.foldingModel = null; this.foldingModelPromise = null; @@ -229,15 +236,16 @@ export class FoldingController implements IEditorContribution { } this.rangeProvider = new IndentRangeProvider(editorModel); // fallback - if (this._useFoldingProviders) { + + if (this._useFoldingProviders && this.foldingModel) { let foldingProviders = FoldingRangeProviderRegistry.ordered(this.foldingModel.textModel); - if (foldingProviders.length === 0 && this.foldingStateMemento) { - this.rangeProvider = new InitializingRangeProvider(editorModel, this.foldingStateMemento.collapsedRegions, () => { + if (foldingProviders.length === 0 && this.foldingStateMemento && this.foldingStateMemento.collapsedRegions) { + const rangeProvider = this.rangeProvider = new InitializingRangeProvider(editorModel, this.foldingStateMemento.collapsedRegions, () => { // if after 30 the InitializingRangeProvider is still not replaced, force a refresh this.foldingStateMemento = null; this.onFoldingStrategyChanged(); }, 30000); - return this.rangeProvider; // keep memento in case there are still no foldingProviders on the next request. + return rangeProvider; // keep memento in case there are still no foldingProviders on the next request. } else if (foldingProviders.length > 0) { this.rangeProvider = new SyntaxRangeProvider(editorModel, foldingProviders); } @@ -257,25 +265,26 @@ export class FoldingController implements IEditorContribution { this.foldingRegionPromise = null; } this.foldingModelPromise = this.updateScheduler.trigger(() => { - if (!this.foldingModel) { // null if editor has been disposed, or folding turned off + const foldingModel = this.foldingModel; + if (!foldingModel) { // null if editor has been disposed, or folding turned off return null; } - let foldingRegionPromise = this.foldingRegionPromise = createCancelablePromise(token => this.getRangeProvider(this.foldingModel.textModel).compute(token)); + let foldingRegionPromise = this.foldingRegionPromise = createCancelablePromise(token => this.getRangeProvider(foldingModel.textModel).compute(token)); return foldingRegionPromise.then(foldingRanges => { if (foldingRanges && foldingRegionPromise === this.foldingRegionPromise) { // new request or cancelled in the meantime? // some cursors might have moved into hidden regions, make sure they are in expanded regions let selections = this.editor.getSelections(); let selectionLineNumbers = selections ? selections.map(s => s.startLineNumber) : []; - this.foldingModel.update(foldingRanges, selectionLineNumbers); + foldingModel.update(foldingRanges, selectionLineNumbers); } - return this.foldingModel; + return foldingModel; }); }); } } private onHiddenRangesChanges(hiddenRanges: IRange[]) { - if (hiddenRanges.length) { + if (this.hiddenRangeModel && hiddenRanges.length) { let selections = this.editor.getSelections(); if (selections) { if (this.hiddenRangeModel.adjustSelections(selections)) { @@ -287,20 +296,24 @@ export class FoldingController implements IEditorContribution { } private onCursorPositionChanged() { - if (this.hiddenRangeModel.hasRanges()) { - this.cursorChangedScheduler.schedule(); + if (this.hiddenRangeModel && this.hiddenRangeModel.hasRanges()) { + this.cursorChangedScheduler!.schedule(); } } private revealCursor() { - this.getFoldingModel().then(foldingModel => { // null is returned if folding got disabled in the meantime + const foldingModel = this.getFoldingModel(); + if (!foldingModel) { + return; + } + foldingModel.then(foldingModel => { // null is returned if folding got disabled in the meantime if (foldingModel) { let selections = this.editor.getSelections(); if (selections && selections.length > 0) { - let toToggle = []; + let toToggle: FoldingRegion[] = []; for (let selection of selections) { let lineNumber = selection.selectionStartLineNumber; - if (this.hiddenRangeModel.isHidden(lineNumber)) { + if (this.hiddenRangeModel && this.hiddenRangeModel.isHidden(lineNumber)) { toToggle.push(...foldingModel.getAllRegionsAtLine(lineNumber, r => r.isCollapsed && lineNumber > r.startLineNumber)); } } @@ -314,18 +327,19 @@ export class FoldingController implements IEditorContribution { } - private mouseDownInfo: { lineNumber: number, iconClicked: boolean }; + private mouseDownInfo: { lineNumber: number, iconClicked: boolean } | null; private onEditorMouseDown(e: IEditorMouseEvent): void { this.mouseDownInfo = null; - let range = e.target.range; - if (!this.hiddenRangeModel || !range) { + + 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 MouseTargetType.GUTTER_LINE_DECORATIONS: @@ -368,7 +382,8 @@ export class FoldingController implements IEditorContribution { } private onEditorMouseUp(e: IEditorMouseEvent): void { - if (!this.mouseDownInfo) { + const foldingModel = this.getFoldingModel(); + if (!foldingModel || !this.mouseDownInfo || !e.target) { return; } let lineNumber = this.mouseDownInfo.lineNumber; @@ -385,12 +400,12 @@ export class FoldingController implements IEditorContribution { } } else { let model = this.editor.getModel(); - if (range.startColumn !== model.getLineMaxColumn(lineNumber)) { + if (!model || range.startColumn !== model.getLineMaxColumn(lineNumber)) { return; } } - this.getFoldingModel().then(foldingModel => { + foldingModel.then(foldingModel => { if (foldingModel) { let region = foldingModel.getRegionAtLine(lineNumber); if (region && region.startLineNumber === lineNumber) { @@ -428,7 +443,10 @@ abstract class FoldingAction extends EditorAction { return foldingModelPromise.then(foldingModel => { if (foldingModel) { this.invoke(foldingController, foldingModel, editor, args); - foldingController.reveal(editor.getSelection().getStartPosition()); + const selection = editor.getSelection(); + if (selection) { + foldingController.reveal(selection.getStartPosition()); + } } }); } @@ -626,7 +644,11 @@ class FoldAllBlockCommentsAction extends FoldingAction { if (foldingModel.regions.hasTypes()) { setCollapseStateForType(foldingModel, FoldingRangeKind.Comment.value, true); } else { - let comments = LanguageConfigurationRegistry.getComments(editor.getModel().getLanguageIdentifier().id); + const editorModel = editor.getModel(); + if (!editorModel) { + return; + } + let comments = LanguageConfigurationRegistry.getComments(editorModel.getLanguageIdentifier().id); if (comments && comments.blockCommentStartToken) { let regExp = new RegExp('^\\s*' + escapeRegExpCharacters(comments.blockCommentStartToken)); setCollapseStateForMatchingLines(foldingModel, regExp, true); @@ -655,7 +677,11 @@ class FoldAllRegionsAction extends FoldingAction { if (foldingModel.regions.hasTypes()) { setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, true); } else { - let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); + const editorModel = editor.getModel(); + if (!editorModel) { + return; + } + let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editorModel.getLanguageIdentifier().id); if (foldingRules && foldingRules.markers && foldingRules.markers.start) { let regExp = new RegExp(foldingRules.markers.start); setCollapseStateForMatchingLines(foldingModel, regExp, true); @@ -684,7 +710,11 @@ class UnfoldAllRegionsAction extends FoldingAction { if (foldingModel.regions.hasTypes()) { setCollapseStateForType(foldingModel, FoldingRangeKind.Region.value, false); } else { - let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editor.getModel().getLanguageIdentifier().id); + const editorModel = editor.getModel(); + if (!editorModel) { + return; + } + let foldingRules = LanguageConfigurationRegistry.getFoldingRules(editorModel.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 06ee89f0e52..90b33321636 100644 --- a/src/vs/editor/contrib/folding/foldingModel.ts +++ b/src/vs/editor/contrib/folding/foldingModel.ts @@ -10,7 +10,7 @@ import { FoldingRegions, ILineRange, FoldingRegion } from './foldingRanges'; export interface IDecorationProvider { getDecorationOption(isCollapsed: boolean): IModelDecorationOptions; deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[]; - changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T; + changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T | null; } export interface FoldingModelChangeEvent { @@ -64,7 +64,7 @@ export class FoldingModel { } public update(newRegions: FoldingRegions, blockedLineNumers: number[] = []): void { - let newEditorDecorations = []; + let newEditorDecorations: IModelDeltaDecoration[] = []; let isBlocked = (startLineNumber, endLineNumber) => { for (let blockedLineNumber of blockedLineNumers) { @@ -138,7 +138,7 @@ export class FoldingModel { /** * Collapse state memento, for persistence only */ - public getMemento(): CollapseMemento { + public getMemento(): CollapseMemento | undefined { let collapsedRanges: ILineRange[] = []; for (let i = 0; i < this._regions.length; i++) { if (this._regions.isCollapsed(i)) { @@ -153,7 +153,7 @@ export class FoldingModel { if (collapsedRanges.length > 0) { return collapsedRanges; } - return null; + return void 0; } /** @@ -194,7 +194,7 @@ export class FoldingModel { return result; } - getRegionAtLine(lineNumber: number): FoldingRegion { + getRegionAtLine(lineNumber: number): FoldingRegion | null { if (this._regions) { let index = this._regions.findRange(lineNumber); if (index >= 0) { @@ -204,16 +204,16 @@ export class FoldingModel { return null; } - getRegionsInside(region: FoldingRegion, filter?: (r: FoldingRegion, level?: number) => boolean): FoldingRegion[] { - let result = []; - let trackLevel = filter && filter.length === 2; - let levelStack: FoldingRegion[] = trackLevel ? [] : null; + getRegionsInside(region: FoldingRegion | null, filter?: (r: FoldingRegion, level?: number) => boolean): FoldingRegion[] { + let result: FoldingRegion[] = []; let index = region ? region.regionIndex + 1 : 0; let endLineNumber = region ? region.endLineNumber : Number.MAX_VALUE; - for (let i = index, len = this._regions.length; i < len; i++) { - let current = this._regions.toRegion(i); - if (this._regions.getStartLineNumber(i) < endLineNumber) { - if (trackLevel) { + + if (filter && filter.length === 2) { + const levelStack: FoldingRegion[] = []; + for (let i = index, len = this._regions.length; i < len; i++) { + let current = this._regions.toRegion(i); + if (this._regions.getStartLineNumber(i) < endLineNumber) { while (levelStack.length > 0 && !current.containedBy(levelStack[levelStack.length - 1])) { levelStack.pop(); } @@ -221,11 +221,20 @@ export class FoldingModel { if (filter(current, levelStack.length)) { result.push(current); } - } else if (!filter || filter(current)) { - result.push(current); + } else { + break; + } + } + } else { + for (let i = index, len = this._regions.length; i < len; i++) { + let current = this._regions.toRegion(i); + if (this._regions.getStartLineNumber(i) < endLineNumber) { + if (!filter || filter(current)) { + result.push(current); + } + } else { + break; } - } else { - break; } } return result; @@ -242,7 +251,7 @@ export class FoldingModel { * @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model. */ export function setCollapseStateLevelsDown(foldingModel: FoldingModel, doCollapse: boolean, levels = Number.MAX_VALUE, lineNumbers?: number[]) { - let toToggle = []; + let toToggle: FoldingRegion[] = []; if (lineNumbers && lineNumbers.length > 0) { for (let lineNumber of lineNumbers) { let region = foldingModel.getRegionAtLine(lineNumber); @@ -251,13 +260,13 @@ export function setCollapseStateLevelsDown(foldingModel: FoldingModel, doCollaps toToggle.push(region); } if (levels > 1) { - let regionsInside = foldingModel.getRegionsInside(region, (r, level) => r.isCollapsed !== doCollapse && level < levels); + let regionsInside = foldingModel.getRegionsInside(region, (r, level: number) => r.isCollapsed !== doCollapse && level < levels); toToggle.push(...regionsInside); } } } } else { - let regionsInside = foldingModel.getRegionsInside(null, (r, level) => r.isCollapsed !== doCollapse && level < levels); + let regionsInside = foldingModel.getRegionsInside(null, (r, level: number) => r.isCollapsed !== doCollapse && level < levels); toToggle.push(...regionsInside); } foldingModel.toggleCollapseState(toToggle); @@ -270,7 +279,7 @@ export function setCollapseStateLevelsDown(foldingModel: FoldingModel, doCollaps * @param lineNumbers the location of the regions to collapse or expand, or if not set, all regions in the model. */ export function setCollapseStateLevelsUp(foldingModel: FoldingModel, doCollapse: boolean, levels: number, lineNumbers: number[]) { - let toToggle = []; + let toToggle: FoldingRegion[] = []; for (let lineNumber of lineNumbers) { let regions = foldingModel.getAllRegionsAtLine(lineNumber, (region, level) => region.isCollapsed !== doCollapse && level <= levels); toToggle.push(...regions); @@ -297,7 +306,7 @@ export function setCollapseStateAtLevel(foldingModel: FoldingModel, foldLevel: n export function setCollapseStateForMatchingLines(foldingModel: FoldingModel, regExp: RegExp, doCollapse: boolean): void { let editorModel = foldingModel.textModel; let regions = foldingModel.regions; - let toToggle = []; + let toToggle: FoldingRegion[] = []; for (let i = regions.length - 1; i >= 0; i--) { if (doCollapse !== regions.isCollapsed(i)) { let startLineNumber = regions.getStartLineNumber(i); @@ -315,7 +324,7 @@ export function setCollapseStateForMatchingLines(foldingModel: FoldingModel, reg */ export function setCollapseStateForType(foldingModel: FoldingModel, type: string, doCollapse: boolean): void { let regions = foldingModel.regions; - let toToggle = []; + let toToggle: FoldingRegion[] = []; for (let i = regions.length - 1; i >= 0; i--) { if (doCollapse !== regions.isCollapsed(i) && type === regions.getType(i)) { toToggle.push(regions.toRegion(i)); diff --git a/src/vs/editor/contrib/folding/foldingRanges.ts b/src/vs/editor/contrib/folding/foldingRanges.ts index 15027db5096..765d55e0d39 100644 --- a/src/vs/editor/contrib/folding/foldingRanges.ts +++ b/src/vs/editor/contrib/folding/foldingRanges.ts @@ -18,9 +18,9 @@ export class FoldingRegions { private _endIndexes: Uint32Array; private _collapseStates: Uint32Array; private _parentsComputed: boolean; - private _types: string[] | undefined; + private _types: (string | undefined)[] | undefined; - constructor(startIndexes: Uint32Array, endIndexes: Uint32Array, types?: string[]) { + constructor(startIndexes: Uint32Array, endIndexes: Uint32Array, types?: (string | undefined)[]) { if (startIndexes.length !== endIndexes.length || startIndexes.length > MAX_FOLDING_REGIONS) { throw new Error('invalid startIndexes or endIndexes size'); } @@ -33,7 +33,7 @@ export class FoldingRegions { private ensureParentIndices() { if (!this._parentsComputed) { this._parentsComputed = true; - let parentIndexes = []; + let parentIndexes: number[] = []; let isInsideLast = (startLineNumber: number, endLineNumber: number) => { let index = parentIndexes[parentIndexes.length - 1]; return this.getStartLineNumber(index) <= startLineNumber && this.getEndLineNumber(index) >= endLineNumber; @@ -144,7 +144,7 @@ export class FoldingRegions { } public toString() { - let res = []; + let res: string[] = []; for (let i = 0; i < this.length; i++) { res[i] = `[${this.isCollapsed(i) ? '+' : '-'}] ${this.getStartLineNumber(i)}/${this.getEndLineNumber(i)}`; } diff --git a/src/vs/editor/contrib/folding/hiddenRangeModel.ts b/src/vs/editor/contrib/folding/hiddenRangeModel.ts index 0caf73939a8..d93e3c6b823 100644 --- a/src/vs/editor/contrib/folding/hiddenRangeModel.ts +++ b/src/vs/editor/contrib/folding/hiddenRangeModel.ts @@ -13,7 +13,7 @@ import { findFirstInSorted } from 'vs/base/common/arrays'; export class HiddenRangeModel { private _foldingModel: FoldingModel; private _hiddenRanges: IRange[]; - private _foldingModelListener: IDisposable; + private _foldingModelListener: IDisposable | null; private _updateEventEmitter = new Emitter(); public get onDidChange(): Event { return this._updateEventEmitter.event; } @@ -70,7 +70,7 @@ export class HiddenRangeModel { if (!Array.isArray(state) || state.length === 0) { return false; } - let hiddenRanges = []; + let hiddenRanges: IRange[] = []; for (let r of state) { if (!r.startLineNumber || !r.endLineNumber) { return false; @@ -104,7 +104,7 @@ export class HiddenRangeModel { public adjustSelections(selections: Selection[]): boolean { let hasChanges = false; let editorModel = this._foldingModel.textModel; - let lastRange = null; + let lastRange: IRange | null = null; let adjustLine = (line: number) => { if (!lastRange || !isInside(line, lastRange)) { @@ -148,7 +148,7 @@ export class HiddenRangeModel { function isInside(line: number, range: IRange) { return line >= range.startLineNumber && line <= range.endLineNumber; } -function findRange(ranges: IRange[], line: number): IRange { +function findRange(ranges: IRange[], line: number): IRange | null { let i = findFirstInSorted(ranges, r => line < r.startLineNumber) - 1; if (i >= 0 && ranges[i].endLineNumber >= line) { return ranges[i]; diff --git a/src/vs/editor/contrib/folding/indentRangeProvider.ts b/src/vs/editor/contrib/folding/indentRangeProvider.ts index 36daedfc577..3804acfeee6 100644 --- a/src/vs/editor/contrib/folding/indentRangeProvider.ts +++ b/src/vs/editor/contrib/folding/indentRangeProvider.ts @@ -28,7 +28,7 @@ export class IndentRangeProvider implements RangeProvider { compute(cancelationToken: CancellationToken): Thenable { let foldingRules = LanguageConfigurationRegistry.getFoldingRules(this.editorModel.getLanguageIdentifier().id); - let offSide = foldingRules && foldingRules.offSide; + let offSide = foldingRules && !!foldingRules.offSide; let markers = foldingRules && foldingRules.markers; return Promise.resolve(computeRanges(this.editorModel, offSide, markers)); } @@ -113,7 +113,7 @@ export function computeRanges(model: ITextModel, offSide: boolean, markers?: Fol const tabSize = model.getOptions().tabSize; let result = new RangesCollector(foldingRangesLimit); - let pattern = void 0; + let pattern: RegExp | undefined = void 0; if (markers) { pattern = new RegExp(`(${markers.start.source})|(?:${markers.end.source})`); } diff --git a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts index fcbc571a4ce..5d7c1b28a27 100644 --- a/src/vs/editor/contrib/folding/syntaxRangeProvider.ts +++ b/src/vs/editor/contrib/folding/syntaxRangeProvider.ts @@ -28,7 +28,7 @@ export class SyntaxRangeProvider implements RangeProvider { constructor(private editorModel: ITextModel, private providers: FoldingRangeProvider[], private limit = MAX_FOLDING_REGIONS) { } - compute(cancellationToken: CancellationToken): Thenable { + compute(cancellationToken: CancellationToken): Thenable { return collectSyntaxRanges(this.providers, this.editorModel, cancellationToken).then(ranges => { if (ranges) { let res = sanitizeRanges(ranges, this.limit); @@ -73,7 +73,7 @@ export class RangesCollector { private _endIndexes: number[]; private _nestingLevels: number[]; private _nestingLevelCounts: number[]; - private _types: string[]; + private _types: (string | undefined)[]; private _length: number; private _foldingRangesLimit: number; @@ -87,7 +87,7 @@ export class RangesCollector { this._foldingRangesLimit = foldingRangesLimit; } - public add(startLineNumber: number, endLineNumber: number, type: string, nestingLevel: number) { + public add(startLineNumber: number, endLineNumber: number, type: string | undefined, nestingLevel: number) { if (startLineNumber > MAX_LINE_NUMBER || endLineNumber > MAX_LINE_NUMBER) { return; } @@ -127,7 +127,7 @@ export class RangesCollector { let startIndexes = new Uint32Array(this._foldingRangesLimit); let endIndexes = new Uint32Array(this._foldingRangesLimit); - let types = []; + let types: (string | undefined)[] = []; for (let i = 0, k = 0; i < this._length; i++) { let level = this._nestingLevels[i]; if (level < maxLevel || (level === maxLevel && entries++ < this._foldingRangesLimit)) { @@ -155,8 +155,8 @@ export function sanitizeRanges(rangeData: IFoldingRangeData[], limit: number): F }); let collector = new RangesCollector(limit); - let top: IFoldingRangeData | null = null; - let previous = []; + let top: IFoldingRangeData | undefined = void 0; + let previous: IFoldingRangeData[] = []; for (let entry of sorted) { if (!top) { top = entry; diff --git a/src/vs/editor/contrib/folding/test/foldingModel.test.ts b/src/vs/editor/contrib/folding/test/foldingModel.test.ts index 8eee1c29704..fae51d077ef 100644 --- a/src/vs/editor/contrib/folding/test/foldingModel.test.ts +++ b/src/vs/editor/contrib/folding/test/foldingModel.test.ts @@ -38,7 +38,7 @@ export class TestDecorationProvider { return this.model.deltaDecorations(oldDecorations, newDecorations); } - changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T { + changeDecorations(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): (T | null) { return this.model.changeDecorations(callback); } } @@ -48,9 +48,9 @@ suite('Folding Model', () => { return { startLineNumber, endLineNumber, isCollapsed }; } - function assertRegion(actual: FoldingRegion, expected: ExpectedRegion, message?: string) { + function assertRegion(actual: FoldingRegion | null, expected: ExpectedRegion | null, message?: string) { assert.equal(!!actual, !!expected, message); - if (actual) { + if (actual && expected) { assert.equal(actual.startLineNumber, expected.startLineNumber, message); assert.equal(actual.endLineNumber, expected.endLineNumber, message); assert.equal(actual.isCollapsed, expected.isCollapsed, message); @@ -58,7 +58,7 @@ suite('Folding Model', () => { } function assertFoldedRanges(foldingModel: FoldingModel, expectedRegions: ExpectedRegion[], message?: string) { - let actualRanges = []; + let actualRanges: ExpectedRegion[] = []; let actual = foldingModel.regions; for (let i = 0; i < actual.length; i++) { if (actual.isCollapsed(i)) { @@ -69,7 +69,7 @@ suite('Folding Model', () => { } function assertRanges(foldingModel: FoldingModel, expectedRegions: ExpectedRegion[], message?: string) { - let actualRanges = []; + let actualRanges: ExpectedRegion[] = []; let actual = foldingModel.regions; for (let i = 0; i < actual.length; i++) { actualRanges.push(r(actual.getStartLineNumber(i), actual.getEndLineNumber(i), actual.isCollapsed(i))); @@ -96,7 +96,7 @@ suite('Folding Model', () => { try { let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel)); - let ranges = computeRanges(textModel, false, null); + let ranges = computeRanges(textModel, false, void 0); foldingModel.update(ranges); let r1 = r(1, 3, false); @@ -135,7 +135,7 @@ suite('Folding Model', () => { try { let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel)); - let ranges = computeRanges(textModel, false, null); + let ranges = computeRanges(textModel, false, void 0); foldingModel.update(ranges); let r1 = r(1, 3, false); @@ -144,17 +144,17 @@ suite('Folding Model', () => { assertRanges(foldingModel, [r1, r2, r3]); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1)!]); foldingModel.update(ranges); assertRanges(foldingModel, [r(1, 3, true), r2, r3]); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(5)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(5)!]); foldingModel.update(ranges); assertRanges(foldingModel, [r(1, 3, true), r2, r(5, 6, true)]); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(7)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(7)!]); foldingModel.update(ranges); assertRanges(foldingModel, [r(1, 3, true), r(4, 7, true), r(5, 6, true)]); @@ -181,7 +181,7 @@ suite('Folding Model', () => { try { let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel)); - let ranges = computeRanges(textModel, false, null); + let ranges = computeRanges(textModel, false, void 0); foldingModel.update(ranges); let r1 = r(1, 3, false); @@ -189,11 +189,11 @@ suite('Folding Model', () => { let r3 = r(5, 6, false); assertRanges(foldingModel, [r1, r2, r3]); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(2), foldingModel.getRegionAtLine(5)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(2)!, foldingModel.getRegionAtLine(5)!]); textModel.applyEdits([EditOperation.insert(new Position(4, 1), '//hello\n')]); - foldingModel.update(computeRanges(textModel, false, null)); + foldingModel.update(computeRanges(textModel, false, void 0)); assertRanges(foldingModel, [r(1, 3, true), r(5, 8, false), r(6, 7, true)]); } finally { @@ -221,7 +221,7 @@ suite('Folding Model', () => { try { let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel)); - let ranges = computeRanges(textModel, false, null); + let ranges = computeRanges(textModel, false, void 0); foldingModel.update(ranges); let r1 = r(1, 12, false); @@ -231,11 +231,11 @@ suite('Folding Model', () => { let r5 = r(9, 11, false); assertRanges(foldingModel, [r1, r2, r3, r4, r5]); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(6)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(6)!]); textModel.applyEdits([EditOperation.delete(new Range(6, 11, 9, 0))]); - foldingModel.update(computeRanges(textModel, false, null)); + foldingModel.update(computeRanges(textModel, false, void 0)); assertRanges(foldingModel, [r(1, 9, false), r(2, 8, false), r(3, 5, false), r(6, 8, false)]); } finally { @@ -258,7 +258,7 @@ suite('Folding Model', () => { try { let foldingModel = new FoldingModel(textModel, new TestDecorationProvider(textModel)); - let ranges = computeRanges(textModel, false, null); + let ranges = computeRanges(textModel, false, void 0); foldingModel.update(ranges); let r1 = r(1, 3, false); diff --git a/src/vs/editor/contrib/folding/test/foldingRanges.test.ts b/src/vs/editor/contrib/folding/test/foldingRanges.test.ts index 282fb9d6346..dd572ec9850 100644 --- a/src/vs/editor/contrib/folding/test/foldingRanges.test.ts +++ b/src/vs/editor/contrib/folding/test/foldingRanges.test.ts @@ -18,7 +18,7 @@ let markers: FoldingMarkers = { suite('FoldingRanges', () => { test('test max folding regions', () => { - let lines = []; + let lines: string[] = []; let nRegions = MAX_FOLDING_REGIONS; for (let i = 0; i < nRegions; i++) { lines.push('#region'); @@ -83,7 +83,7 @@ suite('FoldingRanges', () => { }); test('setCollapsed', () => { - let lines = []; + let lines: string[] = []; let nRegions = 500; for (let i = 0; i < nRegions; i++) { lines.push('#region'); diff --git a/src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts b/src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts index 9cc36f53790..5c33929fa2d 100644 --- a/src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts +++ b/src/vs/editor/contrib/folding/test/hiddenRangeModel.test.ts @@ -44,10 +44,10 @@ suite('Hidden Range Model', () => { assert.equal(hiddenRangeModel.hasRanges(), false); - let ranges = computeRanges(textModel, false, null); + let ranges = computeRanges(textModel, false, void 0); foldingModel.update(ranges); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1), foldingModel.getRegionAtLine(6)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1)!, foldingModel.getRegionAtLine(6)!]); assertRanges(hiddenRangeModel.hiddenRanges, [r(2, 3), r(7, 7)]); assert.equal(hiddenRangeModel.hasRanges(), true); @@ -62,7 +62,7 @@ suite('Hidden Range Model', () => { assert.equal(hiddenRangeModel.isHidden(9), false); assert.equal(hiddenRangeModel.isHidden(10), false); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(4)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(4)!]); assertRanges(hiddenRangeModel.hiddenRanges, [r(2, 3), r(5, 9)]); assert.equal(hiddenRangeModel.hasRanges(), true); @@ -77,7 +77,7 @@ suite('Hidden Range Model', () => { assert.equal(hiddenRangeModel.isHidden(9), true); assert.equal(hiddenRangeModel.isHidden(10), false); - foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1), foldingModel.getRegionAtLine(6), foldingModel.getRegionAtLine(4)]); + foldingModel.toggleCollapseState([foldingModel.getRegionAtLine(1)!, foldingModel.getRegionAtLine(6)!, foldingModel.getRegionAtLine(4)!]); assertRanges(hiddenRangeModel.hiddenRanges, []); assert.equal(hiddenRangeModel.hasRanges(), false); assert.equal(hiddenRangeModel.isHidden(1), false); diff --git a/src/vs/editor/contrib/folding/test/indentFold.test.ts b/src/vs/editor/contrib/folding/test/indentFold.test.ts index 9847277908e..ed51ec95bac 100644 --- a/src/vs/editor/contrib/folding/test/indentFold.test.ts +++ b/src/vs/editor/contrib/folding/test/indentFold.test.ts @@ -50,9 +50,9 @@ suite('Indentation Folding', () => { let model = TextModel.createFromString(lines.join('\n')); function assertLimit(maxEntries: number, expectedRanges: IndentRange[], message: string) { - let indentRanges = computeRanges(model, true, null, maxEntries); + let indentRanges = computeRanges(model, true, undefined, maxEntries); assert.ok(indentRanges.length <= maxEntries, 'max ' + message); - let actual = []; + let actual: IndentRange[] = []; for (let i = 0; i < indentRanges.length; i++) { actual.push({ start: indentRanges.getStartLineNumber(i), end: indentRanges.getEndLineNumber(i) }); } diff --git a/src/vs/editor/contrib/folding/test/indentRangeProvider.test.ts b/src/vs/editor/contrib/folding/test/indentRangeProvider.test.ts index a3032a62c08..882c097104d 100644 --- a/src/vs/editor/contrib/folding/test/indentRangeProvider.test.ts +++ b/src/vs/editor/contrib/folding/test/indentRangeProvider.test.ts @@ -18,7 +18,7 @@ function assertRanges(lines: string[], expected: ExpectedIndentRange[], offside: let model = TextModel.createFromString(lines.join('\n')); let actual = computeRanges(model, offside, markers); - let actualRanges = []; + let actualRanges: ExpectedIndentRange[] = []; for (let i = 0; i < actual.length; i++) { actualRanges[i] = r(actual.getStartLineNumber(i), actual.getEndLineNumber(i), actual.getParentIndex(i)); } diff --git a/src/vs/editor/contrib/folding/test/syntaxFold.test.ts b/src/vs/editor/contrib/folding/test/syntaxFold.test.ts index 822fc81cc5f..480b84e5d7c 100644 --- a/src/vs/editor/contrib/folding/test/syntaxFold.test.ts +++ b/src/vs/editor/contrib/folding/test/syntaxFold.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert'; import { TextModel } from 'vs/editor/common/model/textModel'; import { SyntaxRangeProvider } from 'vs/editor/contrib/folding/syntaxRangeProvider'; -import { FoldingRangeProvider, FoldingRange, FoldingContext } from 'vs/editor/common/modes'; +import { FoldingRangeProvider, FoldingRange, FoldingContext, ProviderResult } from 'vs/editor/common/modes'; import { ITextModel } from 'vs/editor/common/model'; import { CancellationToken } from 'vs/base/common/cancellation'; @@ -18,7 +18,7 @@ class TestFoldingRangeProvider implements FoldingRangeProvider { constructor(private model: ITextModel, private ranges: IndentRange[]) { } - provideFoldingRanges(model: ITextModel, context: FoldingContext, token: CancellationToken): FoldingRange[] { + provideFoldingRanges(model: ITextModel, context: FoldingContext, token: CancellationToken): ProviderResult { if (model === this.model) { return this.ranges; } @@ -75,9 +75,11 @@ suite('Syntax folding', () => { async function assertLimit(maxEntries: number, expectedRanges: IndentRange[], message: string) { let indentRanges = await new SyntaxRangeProvider(model, providers, maxEntries).compute(CancellationToken.None); - let actual = []; - for (let i = 0; i < indentRanges.length; i++) { - actual.push({ start: indentRanges.getStartLineNumber(i), end: indentRanges.getEndLineNumber(i) }); + let actual: IndentRange[] = []; + if (indentRanges) { + for (let i = 0; i < indentRanges.length; i++) { + actual.push({ start: indentRanges.getStartLineNumber(i), end: indentRanges.getEndLineNumber(i) }); + } } assert.deepEqual(actual, expectedRanges, message); }