Skip to content

Commit

Permalink
Merge pull request #77762 from LadyCailin/master
Browse files Browse the repository at this point in the history
Move indent right one when the highlighted line is a scope start/end
  • Loading branch information
alexdima authored Feb 6, 2020
2 parents a82789a + 06c034b commit 519e5bb
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 70 deletions.
73 changes: 49 additions & 24 deletions src/vs/editor/common/model/textModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2640,14 +2640,16 @@ export class TextModel extends Disposable implements model.ITextModel {
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 !== 0 && (upLineNumber < 1 || upLineNumber < minLineNumber)) {
if (distance > 1 && (upLineNumber < 1 || upLineNumber < minLineNumber)) {
goUp = false;
}
if (distance !== 0 && (downLineNumber > lineCount || downLineNumber > maxLineNumber)) {
if (distance > 1 && (downLineNumber > lineCount || downLineNumber > maxLineNumber)) {
goDown = false;
}
if (distance > 50000) {
Expand All @@ -2656,10 +2658,9 @@ export class TextModel extends Disposable implements model.ITextModel {
goDown = false;
}

let upLineIndentLevel: number = -1;
if (goUp) {
// compute indent level going up
let upLineIndentLevel: number;

const currentIndent = this._computeIndentLevel(upLineNumber - 1);
if (currentIndent >= 0) {
// This line has content (besides whitespace)
Expand All @@ -2671,30 +2672,11 @@ export class TextModel extends Disposable implements model.ITextModel {
up_resolveIndents(upLineNumber);
upLineIndentLevel = this._getIndentLevelForWhitespaceLine(offSide, up_aboveContentLineIndent, up_belowContentLineIndent);
}

if (distance === 0) {
// This is the initial line number
startLineNumber = upLineNumber;
endLineNumber = downLineNumber;
indent = upLineIndentLevel;
if (indent === 0) {
// No need to continue
return { startLineNumber, endLineNumber, indent };
}
continue;
}

if (upLineIndentLevel >= indent) {
startLineNumber = upLineNumber;
} else {
goUp = false;
}
}

let downLineIndentLevel = -1;
if (goDown) {
// compute indent level going down
let downLineIndentLevel: number;

const currentIndent = this._computeIndentLevel(downLineNumber - 1);
if (currentIndent >= 0) {
// This line has content (besides whitespace)
Expand All @@ -2706,7 +2688,50 @@ export class TextModel extends Disposable implements model.ITextModel {
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 {
Expand Down
124 changes: 78 additions & 46 deletions src/vs/editor/test/common/model/textModelWithTokens.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ suite('TextModel.getLineIndentGuide', () => {

test('getLineIndentGuide one level 2', () => {
assertIndentGuides([
[0, 1, 1, 0, 'A'],
[0, 2, 4, 1, 'A'],
[1, 2, 4, 1, ' A'],
[1, 2, 4, 1, ' A'],
[1, 2, 4, 1, ' A'],
Expand All @@ -601,19 +601,19 @@ suite('TextModel.getLineIndentGuide', () => {

test('getLineIndentGuide two levels', () => {
assertIndentGuides([
[0, 1, 1, 0, 'A'],
[1, 2, 5, 1, ' A'],
[0, 2, 5, 1, 'A'],
[1, 2, 5, 1, ' A'],
[1, 4, 5, 2, ' A'],
[2, 4, 5, 2, ' A'],
[2, 4, 5, 2, ' A'],
], 2);
});

test('getLineIndentGuide three levels', () => {
assertIndentGuides([
[0, 1, 1, 0, 'A'],
[1, 2, 4, 1, ' A'],
[2, 3, 4, 2, ' A'],
[0, 2, 4, 1, 'A'],
[1, 3, 4, 2, ' A'],
[2, 4, 4, 3, ' A'],
[3, 4, 4, 3, ' A'],
[0, 5, 5, 0, 'A'],
], 2);
Expand All @@ -622,64 +622,64 @@ suite('TextModel.getLineIndentGuide', () => {
test('getLineIndentGuide decreasing indent', () => {
assertIndentGuides([
[2, 1, 1, 2, ' A'],
[1, 1, 2, 1, ' A'],
[0, 3, 3, 0, 'A'],
[1, 1, 1, 2, ' A'],
[0, 1, 2, 1, 'A'],
], 2);
});

test('getLineIndentGuide Java', () => {
assertIndentGuides([
/* 1*/[0, 1, 1, 0, 'class A {'],
/* 2*/[1, 2, 9, 1, ' void foo() {'],
/* 1*/[0, 2, 9, 1, 'class A {'],
/* 2*/[1, 3, 4, 2, ' void foo() {'],
/* 3*/[2, 3, 4, 2, ' console.log(1);'],
/* 4*/[2, 3, 4, 2, ' console.log(2);'],
/* 5*/[1, 2, 9, 1, ' }'],
/* 5*/[1, 3, 4, 2, ' }'],
/* 6*/[1, 2, 9, 1, ''],
/* 7*/[1, 2, 9, 1, ' void bar() {'],
/* 7*/[1, 8, 8, 2, ' void bar() {'],
/* 8*/[2, 8, 8, 2, ' console.log(3);'],
/* 9*/[1, 2, 9, 1, ' }'],
/*10*/[0, 10, 10, 0, '}'],
/*11*/[0, 11, 11, 0, 'interface B {'],
/* 9*/[1, 8, 8, 2, ' }'],
/*10*/[0, 2, 9, 1, '}'],
/*11*/[0, 12, 12, 1, 'interface B {'],
/*12*/[1, 12, 12, 1, ' void bar();'],
/*13*/[0, 13, 13, 0, '}'],
/*13*/[0, 12, 12, 1, '}'],
], 2);
});

test('getLineIndentGuide Javadoc', () => {
assertIndentGuides([
[0, 1, 1, 0, '/**'],
[0, 2, 3, 1, '/**'],
[1, 2, 3, 1, ' * Comment'],
[1, 2, 3, 1, ' */'],
[0, 4, 4, 0, 'class A {'],
[0, 5, 6, 1, 'class A {'],
[1, 5, 6, 1, ' void foo() {'],
[1, 5, 6, 1, ' }'],
[0, 7, 7, 0, '}'],
[0, 5, 6, 1, '}'],
], 2);
});

test('getLineIndentGuide Whitespace', () => {
assertIndentGuides([
[0, 1, 1, 0, 'class A {'],
[0, 2, 7, 1, 'class A {'],
[1, 2, 7, 1, ''],
[1, 2, 7, 1, ' void foo() {'],
[2, 4, 5, 2, ' '],
[3, 5, 5, 3, ' return 1;'],
[1, 2, 7, 1, ' }'],
[1, 4, 5, 2, ' void foo() {'],
[2, 4, 5, 2, ' '],
[2, 4, 5, 2, ' return 1;'],
[1, 4, 5, 2, ' }'],
[1, 2, 7, 1, ' '],
[0, 8, 8, 0, '}']
[0, 2, 7, 1, '}']
], 2);
});

test('getLineIndentGuide Tabs', () => {
assertIndentGuides([
[0, 1, 1, 0, 'class A {'],
[0, 2, 7, 1, 'class A {'],
[1, 2, 7, 1, '\t\t'],
[1, 2, 7, 1, '\tvoid foo() {'],
[1, 4, 5, 2, '\tvoid foo() {'],
[2, 4, 5, 2, '\t \t//hello'],
[2, 4, 5, 2, '\t return 2;'],
[1, 2, 7, 1, ' \t}'],
[1, 4, 5, 2, ' \t}'],
[1, 2, 7, 1, ' '],
[0, 8, 8, 0, '}']
[0, 2, 7, 1, '}']
], 4);
});

Expand All @@ -688,59 +688,59 @@ suite('TextModel.getLineIndentGuide', () => {
/* 1*/[0, 1, 1, 0, '/// <reference path="binder.ts"/>'],
/* 2*/[0, 2, 2, 0, ''],
/* 3*/[0, 3, 3, 0, '/* @internal */'],
/* 4*/[0, 4, 4, 0, 'namespace ts {'],
/* 4*/[0, 5, 16, 1, 'namespace ts {'],
/* 5*/[1, 5, 16, 1, ' let nextSymbolId = 1;'],
/* 6*/[1, 5, 16, 1, ' let nextNodeId = 1;'],
/* 7*/[1, 5, 16, 1, ' let nextMergeId = 1;'],
/* 8*/[1, 5, 16, 1, ' let nextFlowId = 1;'],
/* 9*/[1, 5, 16, 1, ''],
/*10*/[1, 5, 16, 1, ' export function getNodeId(node: Node): number {'],
/*11*/[2, 11, 15, 2, ' if (!node.id) {'],
/*10*/[1, 11, 15, 2, ' export function getNodeId(node: Node): number {'],
/*11*/[2, 12, 13, 3, ' if (!node.id) {'],
/*12*/[3, 12, 13, 3, ' node.id = nextNodeId;'],
/*13*/[3, 12, 13, 3, ' nextNodeId++;'],
/*14*/[2, 11, 15, 2, ' }'],
/*14*/[2, 12, 13, 3, ' }'],
/*15*/[2, 11, 15, 2, ' return node.id;'],
/*16*/[1, 5, 16, 1, ' }'],
/*17*/[0, 17, 17, 0, '}']
/*16*/[1, 11, 15, 2, ' }'],
/*17*/[0, 5, 16, 1, '}']
], 4);
});

test('issue #8425 - Missing indentation lines for first level indentation', () => {
assertIndentGuides([
[1, 1, 4, 1, '\tindent1'],
[1, 2, 3, 2, '\tindent1'],
[2, 2, 3, 2, '\t\tindent2'],
[2, 2, 3, 2, '\t\tindent2'],
[1, 1, 4, 1, '\tindent1']
[1, 2, 3, 2, '\tindent1']
], 4);
});

test('issue #8952 - Indentation guide lines going through text on .yml file', () => {
assertIndentGuides([
[0, 1, 1, 0, 'properties:'],
[1, 2, 5, 1, ' emailAddress:'],
[0, 2, 5, 1, 'properties:'],
[1, 3, 5, 2, ' emailAddress:'],
[2, 3, 5, 2, ' - bla'],
[2, 3, 5, 2, ' - length:'],
[2, 5, 5, 3, ' - length:'],
[3, 5, 5, 3, ' max: 255'],
[0, 6, 6, 0, 'getters:']
], 4);
});

test('issue #11892 - Indent guides look funny', () => {
assertIndentGuides([
[0, 1, 1, 0, 'function test(base) {'],
[1, 2, 7, 1, '\tswitch (base) {'],
[2, 3, 6, 2, '\t\tcase 1:'],
[0, 2, 7, 1, 'function test(base) {'],
[1, 3, 6, 2, '\tswitch (base) {'],
[2, 4, 4, 3, '\t\tcase 1:'],
[3, 4, 4, 3, '\t\t\treturn 1;'],
[2, 3, 6, 2, '\t\tcase 2:'],
[2, 6, 6, 3, '\t\tcase 2:'],
[3, 6, 6, 3, '\t\t\treturn 2;'],
[1, 2, 7, 1, '\t}'],
[0, 8, 8, 0, '}']
[0, 2, 7, 1, '}']
], 4);
});

test('issue #12398 - Problem in indent guidelines', () => {
assertIndentGuides([
[2, 1, 2, 2, '\t\t.bla'],
[2, 2, 2, 3, '\t\t.bla'],
[3, 2, 2, 3, '\t\t\tlabel(for)'],
[0, 3, 3, 0, 'include script']
], 4);
Expand All @@ -766,4 +766,36 @@ suite('TextModel.getLineIndentGuide', () => {
assert.deepEqual(actual, { startLineNumber: 2, endLineNumber: 9, indent: 1 });
model.dispose();
});

test('tweaks - no active', () => {
assertIndentGuides([
[0, 1, 1, 0, 'A'],
[0, 2, 2, 0, 'A']
], 2);
});

test('tweaks - inside scope', () => {
assertIndentGuides([
[0, 2, 2, 1, 'A'],
[1, 2, 2, 1, ' A']
], 2);
});

test('tweaks - scope start', () => {
assertIndentGuides([
[0, 2, 2, 1, 'A'],
[1, 2, 2, 1, ' A'],
[0, 2, 2, 1, 'A']
], 2);
});

test('tweaks - empty line', () => {
assertIndentGuides([
[0, 2, 4, 1, 'A'],
[1, 2, 4, 1, ' A'],
[1, 2, 4, 1, ''],
[1, 2, 4, 1, ' A'],
[0, 2, 4, 1, 'A']
], 2);
});
});

0 comments on commit 519e5bb

Please # to comment.