Skip to content

Commit 5252cbd

Browse files
authored
feat: allow separate tabSize and indentSize (#358)
1 parent 1e13384 commit 5252cbd

3 files changed

Lines changed: 82 additions & 39 deletions

File tree

src/api.ts

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import * as editorconfig from 'editorconfig'
2-
import { TextDocument, TextEditorOptions, Uri, window, workspace } from 'vscode'
2+
import {
3+
TextDocument,
4+
TextEditorOptions,
5+
Uri,
6+
window,
7+
workspace,
8+
commands,
9+
} from 'vscode'
310

411
/**
512
* Resolves `TextEditorOptions` for a `TextDocument`, combining the editor's
@@ -15,16 +22,15 @@ export async function resolveTextEditorOptions(
1522
onEmptyConfig?: (relativePath: string) => void
1623
} = {},
1724
) {
18-
const editorconfigSettings = await resolveCoreConfig(doc, {
19-
onBeforeResolve,
20-
})
21-
if (editorconfigSettings) {
22-
return fromEditorConfig(editorconfigSettings, pickWorkspaceDefaults(doc))
25+
const coreConfig = await resolveCoreConfig(doc, { onBeforeResolve })
26+
if (coreConfig) {
27+
const defaults = pickWorkspaceDefaults(doc)
28+
return fromEditorConfig(coreConfig, defaults)
2329
}
2430
if (onEmptyConfig) {
25-
const rp = resolveFile(doc).relativePath
26-
if (rp) {
27-
onEmptyConfig(rp)
31+
const { relativePath } = resolveFile(doc)
32+
if (relativePath) {
33+
onEmptyConfig(relativePath)
2834
}
2935
}
3036
return {}
@@ -72,14 +78,21 @@ export function pickWorkspaceDefaults(doc?: TextDocument): {
7278
* this property value will be `undefined`.
7379
*/
7480
insertSpaces?: boolean
81+
/**
82+
* The number of spaces used for indentation or `undefined` if
83+
* `editor.detectIndentation` is on.
84+
*/
85+
indentSize?: number | string
7586
} {
87+
commands.executeCommand('editor.action.detectIndentation')
7688
const workspaceConfig = workspace.getConfiguration('editor', doc)
7789
const detectIndentation = workspaceConfig.get<boolean>('detectIndentation')
7890

7991
return detectIndentation
8092
? {}
8193
: {
8294
tabSize: workspaceConfig.get<number>('tabSize'),
95+
indentSize: workspaceConfig.get<number | string>('indentSize'),
8396
insertSpaces: workspaceConfig.get<boolean>('insertSpaces'),
8497
}
8598
}
@@ -95,9 +108,7 @@ export async function resolveCoreConfig(
95108
doc: TextDocument,
96109
{
97110
onBeforeResolve,
98-
}: {
99-
onBeforeResolve?: (relativePath: string) => void
100-
} = {},
111+
}: { onBeforeResolve?: (relativePath: string) => void } = {},
101112
): Promise<ResolvedCoreConfig> {
102113
const { fileName, relativePath } = resolveFile(doc)
103114
if (!fileName) {
@@ -107,9 +118,6 @@ export async function resolveCoreConfig(
107118
onBeforeResolve?.(relativePath)
108119
}
109120
const config = await editorconfig.parse(fileName)
110-
if (config.indent_size === 'tab') {
111-
config.indent_size = config.tab_width
112-
}
113121
return config as ResolvedCoreConfig
114122
}
115123

@@ -144,28 +152,39 @@ export function fromEditorConfig(
144152
config: editorconfig.KnownProps = {},
145153
defaults: TextEditorOptions = pickWorkspaceDefaults(),
146154
): TextEditorOptions {
147-
const resolved: TextEditorOptions = {
148-
tabSize:
149-
config.indent_style === 'tab'
150-
? (config.tab_width ?? config.indent_size)
151-
: (config.indent_size ?? config.tab_width),
155+
const resolved: TextEditorOptions = {}
156+
157+
if (Number.isInteger(config.indent_size)) {
158+
resolved.indentSize = config.indent_size
159+
} else if (config.indent_size === 'tab') {
160+
resolved.indentSize = 'tabSize'
152161
}
153-
if (resolved.tabSize === 'tab') {
162+
163+
if (Number.isInteger(config.tab_width)) {
154164
resolved.tabSize = config.tab_width
165+
} else if (Number.isInteger(config.indent_size)) {
166+
resolved.tabSize = config.indent_size
155167
}
156-
return {
157-
...(config.indent_style === 'tab' ||
158-
config.indent_size === 'tab' ||
159-
config.indent_style === 'space'
160-
? {
161-
insertSpaces: config.indent_style === 'space',
162-
}
163-
: {}),
164-
tabSize:
165-
resolved.tabSize && Number(resolved.tabSize) >= 0
166-
? resolved.tabSize
167-
: defaults.tabSize,
168+
169+
if (config.indent_style === 'tab') {
170+
resolved.insertSpaces = false
171+
} else if (config.indent_style === 'space') {
172+
resolved.insertSpaces = true
168173
}
174+
175+
const combined = { ...defaults, ...resolved }
176+
177+
// decouple tabSize from indentSize when possible
178+
if (
179+
!Number.isInteger(config.tab_width) &&
180+
!(combined.insertSpaces && combined.indentSize === 'tabSize') &&
181+
!(config.indent_style === 'tab' && Number.isInteger(config.indent_size)) &&
182+
Number.isInteger(defaults.tabSize)
183+
) {
184+
combined.tabSize = defaults.tabSize
185+
}
186+
187+
return combined
169188
}
170189

171190
/**

src/test/suite/api.test.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ suite('EditorConfig extension', () => {
1919
expected: {
2020
insertSpaces: false,
2121
tabSize: 5,
22+
indentSize: 5,
2223
},
2324
},
2425
{
@@ -46,7 +47,8 @@ suite('EditorConfig extension', () => {
4647
},
4748
expected: {
4849
insertSpaces: true,
49-
tabSize: 5,
50+
tabSize: 4,
51+
indentSize: 5,
5052
},
5153
},
5254
{
@@ -58,7 +60,9 @@ suite('EditorConfig extension', () => {
5860
tabSize: 4,
5961
},
6062
expected: {
61-
tabSize: 5,
63+
insertSpaces: false,
64+
tabSize: 4,
65+
indentSize: 5,
6266
},
6367
},
6468
{
@@ -70,6 +74,7 @@ suite('EditorConfig extension', () => {
7074
tabSize: 4,
7175
},
7276
expected: {
77+
insertSpaces: false,
7378
tabSize: 5,
7479
},
7580
},
@@ -82,7 +87,9 @@ suite('EditorConfig extension', () => {
8287
tabSize: 4,
8388
},
8489
expected: {
85-
tabSize: 5,
90+
insertSpaces: true,
91+
tabSize: 4,
92+
indentSize: 5,
8693
},
8794
},
8895
{
@@ -94,6 +101,7 @@ suite('EditorConfig extension', () => {
94101
tabSize: 4,
95102
},
96103
expected: {
104+
insertSpaces: true,
97105
tabSize: 5,
98106
},
99107
},
@@ -135,6 +143,7 @@ suite('EditorConfig extension', () => {
135143
expected: {
136144
insertSpaces: false,
137145
tabSize: 3,
146+
indentSize: 'tabSize',
138147
},
139148
},
140149
{
@@ -144,6 +153,7 @@ suite('EditorConfig extension', () => {
144153
tabSize: 5,
145154
},
146155
expected: {
156+
insertSpaces: false,
147157
tabSize: 5,
148158
},
149159
},
@@ -154,6 +164,7 @@ suite('EditorConfig extension', () => {
154164
tabSize: 4,
155165
},
156166
expected: {
167+
insertSpaces: true,
157168
tabSize: 4,
158169
},
159170
},
@@ -166,7 +177,8 @@ suite('EditorConfig extension', () => {
166177
defaults: {},
167178
expected: {
168179
insertSpaces: true,
169-
tabSize: 2,
180+
tabSize: 4,
181+
indentSize: 2,
170182
},
171183
},
172184
].forEach(scenario => {

src/test/suite/index.test.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,18 @@ suite('EditorConfig extension', function () {
215215
'tab_width',
216216
'indent-style-space',
217217
])
218-
const expectedTabSize = 2
218+
const expectedTabSize = 8
219+
const expectedIndentSize = 2
219220
assert.strictEqual(
220221
options.tabSize,
221222
expectedTabSize,
222223
`editor has a tabSize of ${options.tabSize} instead of ${expectedTabSize}`,
223224
)
225+
assert.strictEqual(
226+
options.indentSize,
227+
expectedIndentSize,
228+
`editor has an indentSize of ${options.indentSize} instead of ${expectedIndentSize}`,
229+
)
224230
assert.strictEqual(
225231
options.insertSpaces,
226232
true,
@@ -234,12 +240,18 @@ suite('EditorConfig extension', function () {
234240
'tab_width',
235241
'indent-style-tab',
236242
])
237-
const expectedTabSize = 4
243+
const expectedTabSize = 8
244+
const expectedIndentSize = 4
238245
assert.strictEqual(
239246
options.tabSize,
240247
expectedTabSize,
241248
`editor has a tabSize of ${options.tabSize} instead of ${expectedTabSize}`,
242249
)
250+
assert.strictEqual(
251+
options.indentSize,
252+
expectedIndentSize,
253+
`editor has an indentSize of ${options.indentSize} instead of ${expectedIndentSize}`,
254+
)
243255
assert.strictEqual(
244256
options.insertSpaces,
245257
false,

0 commit comments

Comments
 (0)