Example #1
0
export function computeRanges(model: ITextModel, foldEndPattern: RegExp = null, minimumRangeSize: number = 1): IndentRange[] {


	let result: IndentRange[] = [];

	let previousRegions: { indent: number, line: number }[] = [];
	previousRegions.push({ indent: -1, line: model.getLineCount() + 1 }); // sentinel, to make sure there's at least one entry

	for (let line = model.getLineCount(); line > 0; line--) {
		let indent = model.getIndentLevel(line);
		if (indent === -1) {
			continue; // only whitespace
		}

		let previous = previousRegions[previousRegions.length - 1];

		if (previous.indent > indent) {
			// discard all regions with larger indent
			do {
				previousRegions.pop();
				previous = previousRegions[previousRegions.length - 1];
			} while (previous.indent > indent);

			// new folding range
			let endLineNumber = previous.line - 1;

			if (previous.line <= model.getLineCount() && foldEndPattern) {
				let foldEndLineContent = model.getLineContent(previous.line);
				if (previous.indent === indent && foldEndPattern.test(foldEndLineContent)) {
					endLineNumber = previous.line;
				}
			}

			if (endLineNumber - line >= minimumRangeSize) {
				result.push(new IndentRange(line, endLineNumber, indent));
			}
		}
		if (previous.indent === indent) {
			previous.line = line;
		} else { // previous.indent < indent
			// new region with a bigger indent
			previousRegions.push({ indent, line });
		}
	}

	return result.reverse();
}
	public toIndentRanges(model: ITextModel) {
		if (this._length <= this._FoldingRangesLimit) {
			// reverse and create arrays of the exact length
			let startIndexes = new Uint32Array(this._length);
			let endIndexes = new Uint32Array(this._length);
			for (let i = this._length - 1, k = 0; i >= 0; i-- , k++) {
				startIndexes[k] = this._startIndexes[i];
				endIndexes[k] = this._endIndexes[i];
			}
			return new FoldingRanges(startIndexes, endIndexes);
		} else {
			let entries = 0;
			let maxIndent = this._indentOccurrences.length;
			for (let i = 0; i < this._indentOccurrences.length; i++) {
				let n = this._indentOccurrences[i];
				if (n) {
					if (n + entries > this._FoldingRangesLimit) {
						maxIndent = i;
						break;
					}
					entries += n;
				}
			}
			const tabSize = model.getOptions().tabSize;
			// reverse and create arrays of the exact length
			let startIndexes = new Uint32Array(entries);
			let endIndexes = new Uint32Array(entries);
			for (let i = this._length - 1, k = 0; i >= 0; i--) {
				let startIndex = this._startIndexes[i];
				let lineContent = model.getLineContent(startIndex);
				let indent = computeIndentLevel(lineContent, tabSize);
				if (indent < maxIndent) {
					startIndexes[k] = startIndex;
					endIndexes[k] = this._endIndexes[i];
					k++;
				}
			}
			return new FoldingRanges(startIndexes, endIndexes);
		}

	}
export function computeRanges(model: ITextModel, offSide: boolean, markers?: FoldingMarkers, FoldingRangesLimit = MAX_FOLDING_REGIONS_FOR_INDENT_LIMIT): FoldingRanges {
	const tabSize = model.getOptions().tabSize;
	let result = new RangesCollector(FoldingRangesLimit);

	let pattern = void 0;
	if (markers) {
		pattern = new RegExp(`(${markers.start.source})|(?:${markers.end.source})`);
	}

	let previousRegions: PreviousRegion[] = [];
	previousRegions.push({ indent: -1, line: model.getLineCount() + 1, marker: false }); // sentinel, to make sure there's at least one entry

	for (let line = model.getLineCount(); line > 0; line--) {
		let lineContent = model.getLineContent(line);
		let indent = computeIndentLevel(lineContent, tabSize);
		let previous = previousRegions[previousRegions.length - 1];
		if (indent === -1) {
			if (offSide && !previous.marker) {
				// for offSide languages, empty lines are associated to the next block
				previous.line = line;
			}
			continue; // only whitespace
		}
		let m;
		if (pattern && (m = lineContent.match(pattern))) {
			// folding pattern match
			if (m[1]) { // start pattern match
				// discard all regions until the folding pattern
				let i = previousRegions.length - 1;
				while (i > 0 && !previousRegions[i].marker) {
					i--;
				}
				if (i > 0) {
					previousRegions.length = i + 1;
					previous = previousRegions[i];

					// new folding range from pattern, includes the end line
					result.insertFirst(line, previous.line, indent);
					previous.marker = false;
					previous.indent = indent;
					previous.line = line;
					continue;
				} else {
					// no end marker found, treat line as a regular line
				}
			} else { // end pattern match
				previousRegions.push({ indent: -2, line, marker: true });
				continue;
			}
		}
		if (previous.indent > indent) {
			// discard all regions with larger indent
			do {
				previousRegions.pop();
				previous = previousRegions[previousRegions.length - 1];
			} while (previous.indent > indent);

			// new folding range
			let endLineNumber = previous.line - 1;
			if (endLineNumber - line >= 1) { // needs at east size 1
				result.insertFirst(line, endLineNumber, indent);
			}
		}
		if (previous.indent === indent) {
			previous.line = line;
		} else { // previous.indent < indent
			// new region with a bigger indent
			previousRegions.push({ indent, line, marker: false });
		}
	}
	return result.toIndentRanges(model);
}
Example #4
0
export function computeRanges(model: ITextModel, offSide: boolean, markers?: FoldingMarkers, minimumRangeSize: number = 1): IndentRange[] {

	let result: IndentRange[] = [];

	let pattern = void 0;
	if (markers) {
		pattern = new RegExp(`(${markers.start.source})|(?:${markers.end.source})`);
	}

	let previousRegions: PreviousRegion[] = [];
	previousRegions.push({ indent: -1, line: model.getLineCount() + 1, marker: null }); // sentinel, to make sure there's at least one entry

	for (let line = model.getLineCount(); line > 0; line--) {
		let indent = model.getIndentLevel(line);
		let previous = previousRegions[previousRegions.length - 1];
		if (indent === -1) {
			if (offSide) {
				// for offSide languages, empty lines are associated to the next block
				previous.line = line;
			}
			continue; // only whitespace
		}
		let m;
		if (pattern && (m = model.getLineContent(line).match(pattern))) {
			// folding pattern match
			if (m[1]) { // start pattern match
				if (previous.indent >= 0 && !previous.marker) {

					// discard all regions until the folding pattern
					do {
						previousRegions.pop();
						previous = previousRegions[previousRegions.length - 1];
					} while (previous.indent >= 0 && !previous.marker);
				}
				if (previous.marker) {
					// new folding range from pattern, includes the end line
					result.push(new IndentRange(line, previous.line, indent, true));
					previous.marker = null;
					previous.indent = indent;
					previous.line = line;
				}
			} else { // end pattern match
				previousRegions.push({ indent: -2, line, marker: pattern });
			}
		} else {
			if (previous.indent > indent) {
				// discard all regions with larger indent
				do {
					previousRegions.pop();
					previous = previousRegions[previousRegions.length - 1];
				} while (previous.indent > indent);

				// new folding range
				let endLineNumber = previous.line - 1;
				if (endLineNumber - line >= minimumRangeSize) {
					result.push(new IndentRange(line, endLineNumber, indent));
				}
			}
			if (previous.indent === indent) {
				previous.line = line;
			} else { // previous.indent < indent
				// new region with a bigger indent
				previousRegions.push({ indent, line, marker: null });
			}
		}
	}

	return result.reverse();
}
Example #5
0
	public getIndent(index: number) {
		const lineNumber = this.getStartLineNumber(index);
		const tabSize = this._model.getOptions().tabSize;
		const lineContent = this._model.getLineContent(lineNumber);
		return computeIndentLevel(lineContent, tabSize);
	}