in patched-vscode/src/vs/editor/common/model/guidesTextModelPart.ts [41:272]
public getActiveIndentGuide(
lineNumber: number,
minLineNumber: number,
maxLineNumber: number
): IActiveIndentGuideInfo {
this.assertNotDisposed();
const lineCount = this.textModel.getLineCount();
if (lineNumber < 1 || lineNumber > lineCount) {
throw new BugIndicatingError('Illegal value for lineNumber');
}
const foldingRules = this.getLanguageConfiguration(
this.textModel.getLanguageId()
).foldingRules;
const offSide = Boolean(foldingRules && foldingRules.offSide);
let up_aboveContentLineIndex =
-2; /* -2 is a marker for not having computed it */
let up_aboveContentLineIndent = -1;
let up_belowContentLineIndex =
-2; /* -2 is a marker for not having computed it */
let up_belowContentLineIndent = -1;
const up_resolveIndents = (lineNumber: number) => {
if (
up_aboveContentLineIndex !== -1 &&
(up_aboveContentLineIndex === -2 ||
up_aboveContentLineIndex > lineNumber - 1)
) {
up_aboveContentLineIndex = -1;
up_aboveContentLineIndent = -1;
// must find previous line with content
for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {
const indent = this._computeIndentLevel(lineIndex);
if (indent >= 0) {
up_aboveContentLineIndex = lineIndex;
up_aboveContentLineIndent = indent;
break;
}
}
}
if (up_belowContentLineIndex === -2) {
up_belowContentLineIndex = -1;
up_belowContentLineIndent = -1;
// must find next line with content
for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {
const indent = this._computeIndentLevel(lineIndex);
if (indent >= 0) {
up_belowContentLineIndex = lineIndex;
up_belowContentLineIndent = indent;
break;
}
}
}
};
let down_aboveContentLineIndex =
-2; /* -2 is a marker for not having computed it */
let down_aboveContentLineIndent = -1;
let down_belowContentLineIndex =
-2; /* -2 is a marker for not having computed it */
let down_belowContentLineIndent = -1;
const down_resolveIndents = (lineNumber: number) => {
if (down_aboveContentLineIndex === -2) {
down_aboveContentLineIndex = -1;
down_aboveContentLineIndent = -1;
// must find previous line with content
for (let lineIndex = lineNumber - 2; lineIndex >= 0; lineIndex--) {
const indent = this._computeIndentLevel(lineIndex);
if (indent >= 0) {
down_aboveContentLineIndex = lineIndex;
down_aboveContentLineIndent = indent;
break;
}
}
}
if (
down_belowContentLineIndex !== -1 &&
(down_belowContentLineIndex === -2 ||
down_belowContentLineIndex < lineNumber - 1)
) {
down_belowContentLineIndex = -1;
down_belowContentLineIndent = -1;
// must find next line with content
for (let lineIndex = lineNumber; lineIndex < lineCount; lineIndex++) {
const indent = this._computeIndentLevel(lineIndex);
if (indent >= 0) {
down_belowContentLineIndex = lineIndex;
down_belowContentLineIndent = indent;
break;
}
}
}
};
let startLineNumber = 0;
let goUp = true;
let endLineNumber = 0;
let goDown = true;
let indent = 0;
let initialIndent = 0;
for (let distance = 0; goUp || goDown; distance++) {
const upLineNumber = lineNumber - distance;
const downLineNumber = lineNumber + distance;
if (distance > 1 && (upLineNumber < 1 || upLineNumber < minLineNumber)) {
goUp = false;
}
if (
distance > 1 &&
(downLineNumber > lineCount || downLineNumber > maxLineNumber)
) {
goDown = false;
}
if (distance > 50000) {
// stop processing
goUp = false;
goDown = false;
}
let upLineIndentLevel: number = -1;
if (goUp && upLineNumber >= 1) {
// compute indent level going up
const currentIndent = this._computeIndentLevel(upLineNumber - 1);
if (currentIndent >= 0) {
// This line has content (besides whitespace)
// Use the line's indent
up_belowContentLineIndex = upLineNumber - 1;
up_belowContentLineIndent = currentIndent;
upLineIndentLevel = Math.ceil(
currentIndent / this.textModel.getOptions().indentSize
);
} else {
up_resolveIndents(upLineNumber);
upLineIndentLevel = this._getIndentLevelForWhitespaceLine(
offSide,
up_aboveContentLineIndent,
up_belowContentLineIndent
);
}
}
let downLineIndentLevel = -1;
if (goDown && downLineNumber <= lineCount) {
// compute indent level going down
const currentIndent = this._computeIndentLevel(downLineNumber - 1);
if (currentIndent >= 0) {
// This line has content (besides whitespace)
// Use the line's indent
down_aboveContentLineIndex = downLineNumber - 1;
down_aboveContentLineIndent = currentIndent;
downLineIndentLevel = Math.ceil(
currentIndent / this.textModel.getOptions().indentSize
);
} else {
down_resolveIndents(downLineNumber);
downLineIndentLevel = this._getIndentLevelForWhitespaceLine(
offSide,
down_aboveContentLineIndent,
down_belowContentLineIndent
);
}
}
if (distance === 0) {
initialIndent = upLineIndentLevel;
continue;
}
if (distance === 1) {
if (
downLineNumber <= lineCount &&
downLineIndentLevel >= 0 &&
initialIndent + 1 === downLineIndentLevel
) {
// This is the beginning of a scope, we have special handling here, since we want the
// child scope indent to be active, not the parent scope
goUp = false;
startLineNumber = downLineNumber;
endLineNumber = downLineNumber;
indent = downLineIndentLevel;
continue;
}
if (
upLineNumber >= 1 &&
upLineIndentLevel >= 0 &&
upLineIndentLevel - 1 === initialIndent
) {
// This is the end of a scope, just like above
goDown = false;
startLineNumber = upLineNumber;
endLineNumber = upLineNumber;
indent = upLineIndentLevel;
continue;
}
startLineNumber = lineNumber;
endLineNumber = lineNumber;
indent = initialIndent;
if (indent === 0) {
// No need to continue
return { startLineNumber, endLineNumber, indent };
}
}
if (goUp) {
if (upLineIndentLevel >= indent) {
startLineNumber = upLineNumber;
} else {
goUp = false;
}
}
if (goDown) {
if (downLineIndentLevel >= indent) {
endLineNumber = downLineNumber;
} else {
goDown = false;
}
}
}
return { startLineNumber, endLineNumber, indent };
}