Skip to content

Commit d612204

Browse files
authored
(fix) indentation of organize imports (#890)
Use indentation of first line of imports to determine the indentation of the following lines #854
1 parent 3abba67 commit d612204

File tree

4 files changed

+68
-6
lines changed

4 files changed

+68
-6
lines changed

packages/language-server/src/plugins/typescript/features/CodeActionsProvider.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ import {
88
VersionedTextDocumentIdentifier,
99
WorkspaceEdit
1010
} from 'vscode-languageserver';
11-
import { Document, mapRangeToOriginal, isRangeInTag, isInTag } from '../../../lib/documents';
12-
import { pathToUrl, flatten, isNotNullOrUndefined } from '../../../utils';
11+
import {
12+
Document,
13+
mapRangeToOriginal,
14+
isRangeInTag,
15+
isInTag,
16+
getLineAtPosition
17+
} from '../../../lib/documents';
18+
import { pathToUrl, flatten, isNotNullOrUndefined, modifyLines } from '../../../utils';
1319
import { CodeActionsProvider } from '../../interfaces';
1420
import { SnapshotFragment, SvelteSnapshotFragment } from '../DocumentSnapshot';
1521
import { LSAndTSDocResolver } from '../LSAndTSDocResolver';
@@ -84,7 +90,10 @@ export class CodeActionsProviderImpl implements CodeActionsProvider {
8490
mapRangeToOriginal(fragment, convertRange(fragment, edit.span))
8591
);
8692

87-
return TextEdit.replace(range, edit.newText);
93+
return TextEdit.replace(
94+
range,
95+
this.fixIndentationOfImports(edit.newText, range, document)
96+
);
8897
})
8998
);
9099
})
@@ -99,6 +108,22 @@ export class CodeActionsProviderImpl implements CodeActionsProvider {
99108
];
100109
}
101110

111+
private fixIndentationOfImports(edit: string, range: Range, document: Document): string {
112+
// "Organize Imports" will have edits that delete all imports by return empty edits
113+
// and one edit which contains all the organized imports. Fix indentation
114+
// of that one by prepending all lines with the indentation of the first line.
115+
if (!edit || range.start.character === 0) {
116+
return edit;
117+
}
118+
119+
const line = getLineAtPosition(range.start, document.getText());
120+
const leadingChars = line.substring(0, range.start.character);
121+
if (leadingChars.trim() !== '') {
122+
return edit;
123+
}
124+
return modifyLines(edit, (line, idx) => (idx === 0 || !line ? line : leadingChars + line));
125+
}
126+
102127
private checkRemoveImportCodeActionRange(
103128
edit: ts.TextChange,
104129
fragment: SnapshotFragment,

packages/language-server/src/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,22 @@ export function getRegExpMatches(regex: RegExp, str: string) {
107107
}
108108
return matches;
109109
}
110+
111+
/**
112+
* Function to modify each line of a text, preserving the line break style (`\n` or `\r\n`)
113+
*/
114+
export function modifyLines(
115+
text: string,
116+
replacementFn: (line: string, lineIdx: number) => string
117+
): string {
118+
let idx = 0;
119+
return text
120+
.split('\r\n')
121+
.map((l1) =>
122+
l1
123+
.split('\n')
124+
.map((line) => replacementFn(line, idx++))
125+
.join('\n')
126+
)
127+
.join('\r\n');
128+
}

packages/language-server/test/plugins/typescript/features/CodeActionsProvider.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ describe('CodeActionsProvider', () => {
264264
edits: [
265265
{
266266
// eslint-disable-next-line max-len
267-
newText: "import A from './A';\nimport { c } from './c';\n",
267+
newText: "import A from './A';\n import { c } from './c';\n",
268268
range: {
269269
start: {
270270
line: 1,
@@ -339,7 +339,7 @@ describe('CodeActionsProvider', () => {
339339
edits: [
340340
{
341341
newText:
342-
"import { _,_d } from 'svelte-i18n';\nimport { _e } from 'svelte-i18n1';\n",
342+
"import { _,_d } from 'svelte-i18n';\n import { _e } from 'svelte-i18n1';\n",
343343
range: {
344344
end: {
345345
character: 0,

packages/language-server/test/utils.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isBeforeOrEqualToPosition, regexLastIndexOf } from '../src/utils';
1+
import { isBeforeOrEqualToPosition, modifyLines, regexLastIndexOf } from '../src/utils';
22
import { Position } from 'vscode-languageserver';
33
import * as assert from 'assert';
44

@@ -43,4 +43,22 @@ describe('utils', () => {
4343
assert.equal(regexLastIndexOf('<bla blubb={() => hello', /[\W\s]/g), 17);
4444
});
4545
});
46+
47+
describe('#modifyLines', () => {
48+
it('should work', () => {
49+
assert.equal(
50+
modifyLines('a\nb\r\nc\nd', (line) => 1 + line),
51+
'1a\n1b\r\n1c\n1d'
52+
);
53+
});
54+
55+
it('should pass correct line numbers', () => {
56+
const idxs: number[] = [];
57+
modifyLines('a\nb\r\nc\nd', (_, idx) => {
58+
idxs.push(idx);
59+
return _;
60+
});
61+
assert.deepStrictEqual(idxs, [0, 1, 2, 3]);
62+
});
63+
});
4664
});

0 commit comments

Comments
 (0)