[folding] add null checks

This commit is contained in:
Martin Aeschlimann 2018-10-15 15:24:47 +02:00
parent 5d645696cc
commit 957518fdff
14 changed files with 169 additions and 115 deletions

View file

@ -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",

View file

@ -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;

View file

@ -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<FoldingRegions>;
compute(cancelationToken: CancellationToken): Thenable<FoldingRegions | null>;
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<FoldingRegions>;
private rangeProvider: RangeProvider | null;
private foldingRegionPromise: CancelablePromise<FoldingRegions | null> | null;
private foldingStateMemento: FoldingStateMemento;
private foldingStateMemento: FoldingStateMemento | null;
private foldingModelPromise: Thenable<FoldingModel>;
private updateScheduler: Delayer<FoldingModel>;
private foldingModelPromise: Thenable<FoldingModel | null> | null;
private updateScheduler: Delayer<FoldingModel | null> | 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<T> 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<void> {
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<void> {
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<void> {
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);

View file

@ -10,7 +10,7 @@ import { FoldingRegions, ILineRange, FoldingRegion } from './foldingRanges';
export interface IDecorationProvider {
getDecorationOption(isCollapsed: boolean): IModelDecorationOptions;
deltaDecorations(oldDecorations: string[], newDecorations: IModelDeltaDecoration[]): string[];
changeDecorations<T>(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T;
changeDecorations<T>(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));

View file

@ -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)}`;
}

View file

@ -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<IRange[]>();
public get onDidChange(): Event<IRange[]> { 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];

View file

@ -28,7 +28,7 @@ export class IndentRangeProvider implements RangeProvider {
compute(cancelationToken: CancellationToken): Thenable<FoldingRegions> {
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})`);
}

View file

@ -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<FoldingRegions> {
compute(cancellationToken: CancellationToken): Thenable<FoldingRegions | null> {
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;

View file

@ -38,7 +38,7 @@ export class TestDecorationProvider {
return this.model.deltaDecorations(oldDecorations, newDecorations);
}
changeDecorations<T>(callback: (changeAccessor: IModelDecorationsChangeAccessor) => T): T {
changeDecorations<T>(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);

View file

@ -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');

View file

@ -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);

View file

@ -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) });
}

View file

@ -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));
}

View file

@ -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<FoldingRange[]> {
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);
}