Skip to content

Commit a3804b8

Browse files
hugop95azat-io
authored andcommittedNov 19, 2024
fix: Improve ending commas and semicolon behavior
1 parent e2954de commit a3804b8

38 files changed

+1296
-102
lines changed
 

‎rules/sort-array-includes.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ export let sortArray = <MessageIds extends string>(
178178
name:
179179
element.type === 'Literal'
180180
? `${element.value}`
181-
: sourceCode.text.slice(...element.range),
182-
size: rangeToDiff(element.range),
181+
: sourceCode.getText(element),
182+
size: rangeToDiff(element, sourceCode),
183183
node: element,
184184
group,
185185
}

‎rules/sort-classes.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
384384
} else if (member.key.type === 'Identifier') {
385385
;({ name } = member.key)
386386
} else {
387-
name = sourceCode.text.slice(...member.key.range)
387+
name = sourceCode.getText(member.key)
388388
}
389389

390390
let isPrivateHash =
@@ -410,6 +410,7 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
410410
let memberValue: undefined | string
411411
let modifiers: Modifier[] = []
412412
let selectors: Selector[] = []
413+
let addSafetySemicolonWhenInline: boolean = true
413414
if (
414415
member.type === 'MethodDefinition' ||
415416
member.type === 'TSAbstractMethodDefinition'
@@ -424,6 +425,8 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
424425
}
425426
if (member.type === 'TSAbstractMethodDefinition') {
426427
modifiers.push('abstract')
428+
} else {
429+
addSafetySemicolonWhenInline = false
427430
}
428431

429432
if (decorated) {
@@ -469,6 +472,8 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
469472

470473
selectors.push('index-signature')
471474
} else if (member.type === 'StaticBlock') {
475+
addSafetySemicolonWhenInline = false
476+
472477
selectors.push('static-block')
473478

474479
dependencies = extractDependencies(member, true)
@@ -502,7 +507,6 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
502507
selectors.push('accessor-property')
503508
} else {
504509
// Member is necessarily a Property
505-
506510
// Similarly to above for methods, prioritize 'static', 'declare', 'decorated', 'abstract', 'override' and 'readonly'
507511
// over accessibility modifiers
508512
if (member.static) {
@@ -598,12 +602,13 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
598602

599603
let sortingNode: SortingNodeWithDependencies = {
600604
size: overloadSignatureGroupMember
601-
? rangeToDiff(overloadSignatureGroupMember.range)
602-
: rangeToDiff(member.range),
605+
? rangeToDiff(overloadSignatureGroupMember, sourceCode)
606+
: rangeToDiff(member, sourceCode),
603607
group: getGroup(),
604608
node: member,
605609
dependencies,
606610
name,
611+
addSafetySemicolonWhenInline,
607612
dependencyName: getDependencyName(
608613
name,
609614
modifiers.includes('static'),

‎rules/sort-decorators.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ let sortDecorators = (
279279
setCustomGroups(options.customGroups, name)
280280

281281
let sortingNode: SortDecoratorsSortingNode = {
282-
size: rangeToDiff(decorator.range),
282+
size: rangeToDiff(decorator, sourceCode),
283283
node: decorator,
284284
group: getGroup(),
285285
name,

‎rules/sort-enums.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,13 @@ export default createEslintRule<Options, MESSAGE_ID>({
216216
}
217217
let lastSortingNode = accumulator.at(-1)?.at(-1)
218218
let sortingNode: SortingNodeWithDependencies = {
219-
size: rangeToDiff(member.range),
219+
size: rangeToDiff(member, sourceCode),
220220
node: member,
221221
dependencies,
222222
name:
223223
member.id.type === 'Literal'
224224
? `${member.id.value}`
225-
: `${sourceCode.text.slice(...member.id.range)}`,
225+
: `${sourceCode.getText(member.id)}`,
226226
}
227227

228228
if (

‎rules/sort-exports.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
145145
| TSESTree.ExportAllDeclaration,
146146
) => {
147147
let sortingNode: SortExportsSortingNode = {
148-
size: rangeToDiff(node.range),
148+
size: rangeToDiff(node, sourceCode),
149149
name: node.source.value,
150150
node,
151+
addSafetySemicolonWhenInline: true,
151152
}
152153
let lastNode = parts.at(-1)?.at(-1)
153154
if (

‎rules/sort-heritage-clauses.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ const sortHeritageClauses = (
176176
setCustomGroups(options.customGroups, name)
177177

178178
return {
179-
size: rangeToDiff(heritageClause.range),
179+
size: rangeToDiff(heritageClause, sourceCode),
180180
node: heritageClause,
181181
group: getGroup(),
182182
name,

‎rules/sort-imports.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
370370
if (node.moduleReference.type === 'TSExternalModuleReference') {
371371
name = `${node.moduleReference.expression.value}`
372372
} else {
373-
name = sourceCode.text.slice(...node.moduleReference.range)
373+
name = sourceCode.getText(node.moduleReference)
374374
}
375375
} else {
376376
let decl = node.declarations[0].init as TSESTree.CallExpression
@@ -515,9 +515,10 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
515515
}
516516

517517
nodes.push({
518-
size: rangeToDiff(node.range),
518+
size: rangeToDiff(node, sourceCode),
519519
group: getGroup(),
520520
node,
521+
addSafetySemicolonWhenInline: true,
521522
isIgnored:
522523
!options.sortSideEffects &&
523524
isSideEffect &&

‎rules/sort-interfaces.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,11 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
277277
}
278278

279279
let elementSortingNode: SortingNode = {
280-
size: rangeToDiff(element.range),
280+
size: rangeToDiff(element, sourceCode),
281281
node: element,
282282
group: getGroup(),
283283
name,
284+
addSafetySemicolonWhenInline: true,
284285
}
285286

286287
if (

‎rules/sort-intersection-types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ export default createEslintRule<Options, MESSAGE_ID>({
270270

271271
let lastSortingNode = accumulator.at(-1)?.at(-1)
272272
let sortingNode: SortingNode = {
273-
name: sourceCode.text.slice(...type.range),
274-
size: rangeToDiff(type.range),
273+
name: sourceCode.getText(type),
274+
size: rangeToDiff(type, sourceCode),
275275
group: getGroup(),
276276
node: type,
277277
}

‎rules/sort-jsx-props.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
166166

167167
let shouldIgnore = false
168168
if (options.ignorePattern.length) {
169-
let tagName = sourceCode.text.slice(...node.openingElement.name.range)
169+
let tagName = sourceCode.getText(node.openingElement.name)
170170
shouldIgnore = options.ignorePattern.some(pattern =>
171171
matches(tagName, pattern, options.matcher),
172172
)
@@ -202,10 +202,11 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
202202
}
203203

204204
let jsxNode = {
205-
size: rangeToDiff(attribute.range),
205+
size: rangeToDiff(attribute, sourceCode),
206206
group: getGroup(),
207207
node: attribute,
208208
name,
209+
requiresEndingSemicolonOrCommaWhenInline: true,
209210
}
210211

211212
accumulator.at(-1)!.push(jsxNode)

‎rules/sort-maps.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,15 @@ export default createEslintRule<Options, MESSAGE_ID>({
167167
} else if (left.type === 'Literal') {
168168
name = left.raw
169169
} else {
170-
name = sourceCode.text.slice(...left.range)
170+
name = sourceCode.getText(left)
171171
}
172172
} else {
173-
name = sourceCode.text.slice(...element.range)
173+
name = sourceCode.getText(element)
174174
}
175175

176176
let lastSortingNode = formattedMembers.at(-1)?.at(-1)
177177
let sortingNode: SortingNode = {
178-
size: rangeToDiff(element.range),
178+
size: rangeToDiff(element, sourceCode),
179179
node: element,
180180
name,
181181
}

‎rules/sort-named-exports.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
156156

157157
let lastSortingNode = formattedMembers.at(-1)?.at(-1)
158158
let sortingNode: SortingNode = {
159-
size: rangeToDiff(specifier.range),
159+
size: rangeToDiff(specifier, sourceCode),
160160
node: specifier,
161161
group,
162162
name,

‎rules/sort-named-imports.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
171171

172172
let lastSortingNode = formattedMembers.at(-1)?.at(-1)
173173
let sortingNode: SortingNode = {
174-
size: rangeToDiff(specifier.range),
174+
size: rangeToDiff(specifier, sourceCode),
175175
node: specifier,
176176
group,
177177
name,

‎rules/sort-object-types.ts

+2-8
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,6 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
217217
node.members.reduce(
218218
(accumulator: SortObjectTypesSortingNode[][], member) => {
219219
let name: string
220-
let raw = sourceCode.text.slice(
221-
member.range.at(0),
222-
member.range.at(1),
223-
)
224220
let lastSortingNode = accumulator.at(-1)?.at(-1)
225221

226222
let { getGroup, defineGroup, setCustomGroups } =
@@ -268,14 +264,12 @@ export default createEslintRule<Options<string[]>, MESSAGE_ID>({
268264
defineGroup('multiline')
269265
}
270266

271-
let endsWithComma = raw.endsWith(';') || raw.endsWith(',')
272-
let endSize = endsWithComma ? 1 : 0
273-
274267
let sortingNode: SortObjectTypesSortingNode = {
275-
size: rangeToDiff(member.range) - endSize,
268+
size: rangeToDiff(member, sourceCode),
276269
group: getGroup(),
277270
node: member,
278271
name,
272+
addSafetySemicolonWhenInline: true,
279273
}
280274

281275
if (

‎rules/sort-objects.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
416416
} else if (prop.key.type === 'Literal') {
417417
name = `${prop.key.value}`
418418
} else {
419-
name = sourceCode.text.slice(...prop.key.range)
419+
name = sourceCode.getText(prop.key)
420420
}
421421

422422
if (prop.value.type === 'AssignmentPattern') {
@@ -437,7 +437,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
437437
}
438438

439439
let propSortingNode: SortingNodeWithDependencies = {
440-
size: rangeToDiff(prop.range),
440+
size: rangeToDiff(prop, sourceCode),
441441
node: prop,
442442
group: getGroup(),
443443
dependencies,

‎rules/sort-switch-case.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,14 @@ export default createEslintRule<Options, MESSAGE_ID>({
119119
name = 'default'
120120
isDefaultClause = true
121121
} else {
122-
name = sourceCode.text.slice(...caseNode.test.range)
122+
name = sourceCode.getText(caseNode.test)
123123
}
124124

125125
return {
126-
size: rangeToDiff(caseNode.test?.range ?? caseNode.range),
126+
size: rangeToDiff(caseNode.test ?? caseNode, sourceCode),
127127
node: caseNode,
128128
isDefaultClause,
129+
addSafetySemicolonWhenInline: true,
129130
name,
130131
}
131132
},

‎rules/sort-union-types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,8 @@ export default createEslintRule<Options, MESSAGE_ID>({
270270

271271
let lastSortingNode = accumulator.at(-1)?.at(-1)
272272
let sortingNode: SortingNode = {
273-
name: sourceCode.text.slice(...type.range),
274-
size: rangeToDiff(type.range),
273+
name: sourceCode.getText(type),
274+
size: rangeToDiff(type, sourceCode),
275275
group: getGroup(),
276276
node: type,
277277
}

‎rules/sort-variable-declarations.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ export default createEslintRule<Options, MESSAGE_ID>({
240240

241241
let lastSortingNode = accumulator.at(-1)?.at(-1)
242242
let sortingNode: SortingNodeWithDependencies = {
243-
size: rangeToDiff(declaration.range),
243+
size: rangeToDiff(declaration, sourceCode),
244244
node: declaration,
245245
dependencies,
246246
name,

‎test/sort-array-includes.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,60 @@ describe(ruleName, () => {
689689
invalid: [],
690690
},
691691
)
692+
693+
ruleTester.run(
694+
`${ruleName}(${type}): sorts inline elements correctly`,
695+
rule,
696+
{
697+
valid: [],
698+
invalid: [
699+
{
700+
code: dedent`
701+
[
702+
b, a
703+
].includes(value)
704+
`,
705+
output: dedent`
706+
[
707+
a, b
708+
].includes(value)
709+
`,
710+
options: [options],
711+
errors: [
712+
{
713+
messageId: 'unexpectedArrayIncludesOrder',
714+
data: {
715+
left: 'b',
716+
right: 'a',
717+
},
718+
},
719+
],
720+
},
721+
{
722+
code: dedent`
723+
[
724+
b, a,
725+
].includes(value)
726+
`,
727+
output: dedent`
728+
[
729+
a, b,
730+
].includes(value)
731+
`,
732+
options: [options],
733+
errors: [
734+
{
735+
messageId: 'unexpectedArrayIncludesOrder',
736+
data: {
737+
left: 'b',
738+
right: 'a',
739+
},
740+
},
741+
],
742+
},
743+
],
744+
},
745+
)
692746
})
693747

694748
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-classes.test.ts

+334
Original file line numberDiff line numberDiff line change
@@ -4063,6 +4063,340 @@ describe(ruleName, () => {
40634063
invalid: [],
40644064
},
40654065
)
4066+
4067+
describe(`${ruleName}(${type}): sorts inline elements correctly`, () => {
4068+
describe(`${ruleName}(${type}): methods`, () => {
4069+
describe(`${ruleName}(${type}): non-abstract methods`, () => {
4070+
ruleTester.run(
4071+
`${ruleName}(${type}): sorts inline non-abstract methods correctly`,
4072+
rule,
4073+
{
4074+
valid: [],
4075+
invalid: [
4076+
{
4077+
code: dedent`
4078+
class Class {
4079+
b(){} a(){}
4080+
}
4081+
`,
4082+
output: dedent`
4083+
class Class {
4084+
a(){} b(){}
4085+
}
4086+
`,
4087+
options: [options],
4088+
errors: [
4089+
{
4090+
messageId: 'unexpectedClassesOrder',
4091+
data: {
4092+
left: 'b',
4093+
right: 'a',
4094+
},
4095+
},
4096+
],
4097+
},
4098+
{
4099+
code: dedent`
4100+
class Class {
4101+
b(){} a(){};
4102+
}
4103+
`,
4104+
output: dedent`
4105+
class Class {
4106+
a(){} b(){};
4107+
}
4108+
`,
4109+
options: [options],
4110+
errors: [
4111+
{
4112+
messageId: 'unexpectedClassesOrder',
4113+
data: {
4114+
left: 'b',
4115+
right: 'a',
4116+
},
4117+
},
4118+
],
4119+
},
4120+
{
4121+
code: dedent`
4122+
class Class {
4123+
b(){}; a(){}
4124+
}
4125+
`,
4126+
output: dedent`
4127+
class Class {
4128+
a(){}; b(){}
4129+
}
4130+
`,
4131+
options: [options],
4132+
errors: [
4133+
{
4134+
messageId: 'unexpectedClassesOrder',
4135+
data: {
4136+
left: 'b',
4137+
right: 'a',
4138+
},
4139+
},
4140+
],
4141+
},
4142+
],
4143+
},
4144+
)
4145+
})
4146+
4147+
describe(`${ruleName}(${type}): abstract methods`, () => {
4148+
ruleTester.run(
4149+
`${ruleName}(${type}): sorts inline abstract methods correctly`,
4150+
rule,
4151+
{
4152+
valid: [],
4153+
invalid: [
4154+
{
4155+
code: dedent`
4156+
abstract class Class {
4157+
abstract b(); abstract a()
4158+
}
4159+
`,
4160+
output: dedent`
4161+
abstract class Class {
4162+
abstract a(); abstract b();
4163+
}
4164+
`,
4165+
options: [options],
4166+
errors: [
4167+
{
4168+
messageId: 'unexpectedClassesOrder',
4169+
data: {
4170+
left: 'b',
4171+
right: 'a',
4172+
},
4173+
},
4174+
],
4175+
},
4176+
{
4177+
code: dedent`
4178+
abstract class Class {
4179+
abstract b(); abstract a();
4180+
}
4181+
`,
4182+
output: dedent`
4183+
abstract class Class {
4184+
abstract a(); abstract b();
4185+
}
4186+
`,
4187+
options: [options],
4188+
errors: [
4189+
{
4190+
messageId: 'unexpectedClassesOrder',
4191+
data: {
4192+
left: 'b',
4193+
right: 'a',
4194+
},
4195+
},
4196+
],
4197+
},
4198+
],
4199+
},
4200+
)
4201+
})
4202+
})
4203+
4204+
ruleTester.run(
4205+
`${ruleName}(${type}): sorts inline properties correctly`,
4206+
rule,
4207+
{
4208+
valid: [],
4209+
invalid: [
4210+
{
4211+
code: dedent`
4212+
class Class {
4213+
b; a
4214+
}
4215+
`,
4216+
output: dedent`
4217+
class Class {
4218+
a; b;
4219+
}
4220+
`,
4221+
options: [options],
4222+
errors: [
4223+
{
4224+
messageId: 'unexpectedClassesOrder',
4225+
data: {
4226+
left: 'b',
4227+
right: 'a',
4228+
},
4229+
},
4230+
],
4231+
},
4232+
{
4233+
code: dedent`
4234+
class Class {
4235+
b; a;
4236+
}
4237+
`,
4238+
output: dedent`
4239+
class Class {
4240+
a; b;
4241+
}
4242+
`,
4243+
options: [options],
4244+
errors: [
4245+
{
4246+
messageId: 'unexpectedClassesOrder',
4247+
data: {
4248+
left: 'b',
4249+
right: 'a',
4250+
},
4251+
},
4252+
],
4253+
},
4254+
],
4255+
},
4256+
)
4257+
4258+
ruleTester.run(
4259+
`${ruleName}(${type}): sorts inline accessors correctly`,
4260+
rule,
4261+
{
4262+
valid: [],
4263+
invalid: [
4264+
{
4265+
code: dedent`
4266+
class Class {
4267+
accessor b; accessor a
4268+
}
4269+
`,
4270+
output: dedent`
4271+
class Class {
4272+
accessor a; accessor b;
4273+
}
4274+
`,
4275+
options: [options],
4276+
errors: [
4277+
{
4278+
messageId: 'unexpectedClassesOrder',
4279+
data: {
4280+
left: 'b',
4281+
right: 'a',
4282+
},
4283+
},
4284+
],
4285+
},
4286+
{
4287+
code: dedent`
4288+
class Class {
4289+
accessor b; accessor a;
4290+
}
4291+
`,
4292+
output: dedent`
4293+
class Class {
4294+
accessor a; accessor b;
4295+
}
4296+
`,
4297+
options: [options],
4298+
errors: [
4299+
{
4300+
messageId: 'unexpectedClassesOrder',
4301+
data: {
4302+
left: 'b',
4303+
right: 'a',
4304+
},
4305+
},
4306+
],
4307+
},
4308+
],
4309+
},
4310+
)
4311+
4312+
ruleTester.run(
4313+
`${ruleName}(${type}): sorts inline index-signatures correctly`,
4314+
rule,
4315+
{
4316+
valid: [],
4317+
invalid: [
4318+
{
4319+
code: dedent`
4320+
class Class {
4321+
[key: string]: string; [key: number]: string
4322+
}
4323+
`,
4324+
output: dedent`
4325+
class Class {
4326+
[key: number]: string; [key: string]: string;
4327+
}
4328+
`,
4329+
options: [options],
4330+
errors: [
4331+
{
4332+
messageId: 'unexpectedClassesOrder',
4333+
data: {
4334+
left: '[key: string]',
4335+
right: '[key: number]',
4336+
},
4337+
},
4338+
],
4339+
},
4340+
{
4341+
code: dedent`
4342+
class Class {
4343+
[key: string]: string; [key: number]: string;
4344+
}
4345+
`,
4346+
output: dedent`
4347+
class Class {
4348+
[key: number]: string; [key: string]: string;
4349+
}
4350+
`,
4351+
options: [options],
4352+
errors: [
4353+
{
4354+
messageId: 'unexpectedClassesOrder',
4355+
data: {
4356+
left: '[key: string]',
4357+
right: '[key: number]',
4358+
},
4359+
},
4360+
],
4361+
},
4362+
],
4363+
},
4364+
)
4365+
4366+
ruleTester.run(
4367+
`${ruleName}(${type}): sorts inline static-block correctly`,
4368+
rule,
4369+
{
4370+
valid: [],
4371+
invalid: [
4372+
{
4373+
code: dedent`
4374+
class Class {
4375+
a; static {}
4376+
}
4377+
`,
4378+
output: dedent`
4379+
class Class {
4380+
static {} a;
4381+
}
4382+
`,
4383+
options: [options],
4384+
errors: [
4385+
{
4386+
messageId: 'unexpectedClassesGroupOrder',
4387+
data: {
4388+
left: 'a',
4389+
leftGroup: 'property',
4390+
right: 'static',
4391+
rightGroup: 'static-block',
4392+
},
4393+
},
4394+
],
4395+
},
4396+
],
4397+
},
4398+
)
4399+
})
40664400
})
40674401

40684402
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-enums.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,60 @@ describe(ruleName, () => {
584584
invalid: [],
585585
},
586586
)
587+
588+
ruleTester.run(
589+
`${ruleName}(${type}): sorts inline elements correctly`,
590+
rule,
591+
{
592+
valid: [],
593+
invalid: [
594+
{
595+
code: dedent`
596+
enum Enum {
597+
B = "B", A = "A"
598+
}
599+
`,
600+
output: dedent`
601+
enum Enum {
602+
A = "A", B = "B"
603+
}
604+
`,
605+
options: [options],
606+
errors: [
607+
{
608+
messageId: 'unexpectedEnumsOrder',
609+
data: {
610+
left: 'B',
611+
right: 'A',
612+
},
613+
},
614+
],
615+
},
616+
{
617+
code: dedent`
618+
enum Enum {
619+
B = "B", A = "A",
620+
}
621+
`,
622+
output: dedent`
623+
enum Enum {
624+
A = "A", B = "B",
625+
}
626+
`,
627+
options: [options],
628+
errors: [
629+
{
630+
messageId: 'unexpectedEnumsOrder',
631+
data: {
632+
left: 'B',
633+
right: 'A',
634+
},
635+
},
636+
],
637+
},
638+
],
639+
},
640+
)
587641
})
588642

589643
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-exports.test.ts

+46
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,52 @@ describe(ruleName, () => {
516516
invalid: [],
517517
},
518518
)
519+
520+
ruleTester.run(
521+
`${ruleName}(${type}): sorts inline elements correctly`,
522+
rule,
523+
{
524+
valid: [],
525+
invalid: [
526+
{
527+
code: dedent`
528+
export { b } from "b"; export { a } from "a"
529+
`,
530+
output: dedent`
531+
export { a } from "a"; export { b } from "b";
532+
`,
533+
options: [options],
534+
errors: [
535+
{
536+
messageId: 'unexpectedExportsOrder',
537+
data: {
538+
left: 'b',
539+
right: 'a',
540+
},
541+
},
542+
],
543+
},
544+
{
545+
code: dedent`
546+
export { b } from "b"; export { a } from "a";
547+
`,
548+
output: dedent`
549+
export { a } from "a"; export { b } from "b";
550+
`,
551+
options: [options],
552+
errors: [
553+
{
554+
messageId: 'unexpectedExportsOrder',
555+
data: {
556+
left: 'b',
557+
right: 'a',
558+
},
559+
},
560+
],
561+
},
562+
],
563+
},
564+
)
519565
})
520566

521567
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-heritage-clauses.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,60 @@ describe(ruleName, () => {
335335
invalid: [],
336336
},
337337
)
338+
339+
ruleTester.run(
340+
`${ruleName}(${type}): sorts inline elements correctly`,
341+
rule,
342+
{
343+
valid: [],
344+
invalid: [
345+
{
346+
code: dedent`
347+
interface Interface extends
348+
B, A
349+
{}
350+
`,
351+
output: dedent`
352+
interface Interface extends
353+
A, B
354+
{}
355+
`,
356+
options: [options],
357+
errors: [
358+
{
359+
messageId: 'unexpectedHeritageClausesOrder',
360+
data: {
361+
left: 'B',
362+
right: 'A',
363+
},
364+
},
365+
],
366+
},
367+
{
368+
code: dedent`
369+
class Class implements
370+
B, A
371+
{}
372+
`,
373+
output: dedent`
374+
class Class implements
375+
A, B
376+
{}
377+
`,
378+
options: [options],
379+
errors: [
380+
{
381+
messageId: 'unexpectedHeritageClausesOrder',
382+
data: {
383+
left: 'B',
384+
right: 'A',
385+
},
386+
},
387+
],
388+
},
389+
],
390+
},
391+
)
338392
})
339393

340394
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-imports.test.ts

+46
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,52 @@ describe(ruleName, () => {
20602060
},
20612061
)
20622062
})
2063+
2064+
ruleTester.run(
2065+
`${ruleName}(${type}): sorts inline elements correctly`,
2066+
rule,
2067+
{
2068+
valid: [],
2069+
invalid: [
2070+
{
2071+
code: dedent`
2072+
import { b } from "b"; import { a } from "a"
2073+
`,
2074+
output: dedent`
2075+
import { a } from "a"; import { b } from "b";
2076+
`,
2077+
options: [options],
2078+
errors: [
2079+
{
2080+
messageId: 'unexpectedImportsOrder',
2081+
data: {
2082+
left: 'b',
2083+
right: 'a',
2084+
},
2085+
},
2086+
],
2087+
},
2088+
{
2089+
code: dedent`
2090+
import { b } from "b"; import { a } from "a";
2091+
`,
2092+
output: dedent`
2093+
import { a } from "a"; import { b } from "b";
2094+
`,
2095+
options: [options],
2096+
errors: [
2097+
{
2098+
messageId: 'unexpectedImportsOrder',
2099+
data: {
2100+
left: 'b',
2101+
right: 'a',
2102+
},
2103+
},
2104+
],
2105+
},
2106+
],
2107+
},
2108+
)
20632109
})
20642110

20652111
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-interfaces.test.ts

+76
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,82 @@ describe(ruleName, () => {
11781178
},
11791179
)
11801180
})
1181+
1182+
ruleTester.run(
1183+
`${ruleName}(${type}): sorts inline elements correctly`,
1184+
rule,
1185+
{
1186+
valid: [],
1187+
invalid: [
1188+
{
1189+
code: dedent`
1190+
interface Interface {
1191+
b: string, a: string
1192+
}
1193+
`,
1194+
output: dedent`
1195+
interface Interface {
1196+
a: string; b: string,
1197+
}
1198+
`,
1199+
options: [options],
1200+
errors: [
1201+
{
1202+
messageId: 'unexpectedInterfacePropertiesOrder',
1203+
data: {
1204+
left: 'b',
1205+
right: 'a',
1206+
},
1207+
},
1208+
],
1209+
},
1210+
{
1211+
code: dedent`
1212+
interface Interface {
1213+
b: string, a: string;
1214+
}
1215+
`,
1216+
output: dedent`
1217+
interface Interface {
1218+
a: string; b: string,
1219+
}
1220+
`,
1221+
options: [options],
1222+
errors: [
1223+
{
1224+
messageId: 'unexpectedInterfacePropertiesOrder',
1225+
data: {
1226+
left: 'b',
1227+
right: 'a',
1228+
},
1229+
},
1230+
],
1231+
},
1232+
{
1233+
code: dedent`
1234+
interface Interface {
1235+
b: string, a: string,
1236+
}
1237+
`,
1238+
output: dedent`
1239+
interface Interface {
1240+
a: string, b: string,
1241+
}
1242+
`,
1243+
options: [options],
1244+
errors: [
1245+
{
1246+
messageId: 'unexpectedInterfacePropertiesOrder',
1247+
data: {
1248+
left: 'b',
1249+
right: 'a',
1250+
},
1251+
},
1252+
],
1253+
},
1254+
],
1255+
},
1256+
)
11811257
})
11821258

11831259
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-intersection-types.test.ts

+50
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,56 @@ describe(ruleName, () => {
866866
},
867867
)
868868
})
869+
870+
ruleTester.run(
871+
`${ruleName}(${type}): sorts inline elements correctly`,
872+
rule,
873+
{
874+
valid: [],
875+
invalid: [
876+
{
877+
code: dedent`
878+
type T =
879+
& B & A
880+
`,
881+
output: dedent`
882+
type T =
883+
& A & B
884+
`,
885+
options: [options],
886+
errors: [
887+
{
888+
messageId: 'unexpectedIntersectionTypesOrder',
889+
data: {
890+
left: 'B',
891+
right: 'A',
892+
},
893+
},
894+
],
895+
},
896+
{
897+
code: dedent`
898+
type T =
899+
B & A
900+
`,
901+
output: dedent`
902+
type T =
903+
A & B
904+
`,
905+
options: [options],
906+
errors: [
907+
{
908+
messageId: 'unexpectedIntersectionTypesOrder',
909+
data: {
910+
left: 'B',
911+
right: 'A',
912+
},
913+
},
914+
],
915+
},
916+
],
917+
},
918+
)
869919
})
870920

871921
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-named-exports.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,60 @@ describe(ruleName, () => {
456456
},
457457
],
458458
})
459+
460+
ruleTester.run(
461+
`${ruleName}(${type}): sorts inline elements correctly`,
462+
rule,
463+
{
464+
valid: [],
465+
invalid: [
466+
{
467+
code: dedent`
468+
export {
469+
b, a
470+
}
471+
`,
472+
output: dedent`
473+
export {
474+
a, b
475+
}
476+
`,
477+
options: [options],
478+
errors: [
479+
{
480+
messageId: 'unexpectedNamedExportsOrder',
481+
data: {
482+
left: 'b',
483+
right: 'a',
484+
},
485+
},
486+
],
487+
},
488+
{
489+
code: dedent`
490+
export {
491+
b, a,
492+
}
493+
`,
494+
output: dedent`
495+
export {
496+
a, b,
497+
}
498+
`,
499+
options: [options],
500+
errors: [
501+
{
502+
messageId: 'unexpectedNamedExportsOrder',
503+
data: {
504+
left: 'b',
505+
right: 'a',
506+
},
507+
},
508+
],
509+
},
510+
],
511+
},
512+
)
459513
})
460514

461515
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-named-imports.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,60 @@ describe(ruleName, () => {
687687
},
688688
],
689689
})
690+
691+
ruleTester.run(
692+
`${ruleName}(${type}): sorts inline elements correctly`,
693+
rule,
694+
{
695+
valid: [],
696+
invalid: [
697+
{
698+
code: dedent`
699+
import {
700+
b, a
701+
} from 'module'
702+
`,
703+
output: dedent`
704+
import {
705+
a, b
706+
} from 'module'
707+
`,
708+
options: [options],
709+
errors: [
710+
{
711+
messageId: 'unexpectedNamedImportsOrder',
712+
data: {
713+
left: 'b',
714+
right: 'a',
715+
},
716+
},
717+
],
718+
},
719+
{
720+
code: dedent`
721+
import {
722+
b, a,
723+
} from 'module'
724+
`,
725+
output: dedent`
726+
import {
727+
a, b,
728+
} from 'module'
729+
`,
730+
options: [options],
731+
errors: [
732+
{
733+
messageId: 'unexpectedNamedImportsOrder',
734+
data: {
735+
left: 'b',
736+
right: 'a',
737+
},
738+
},
739+
],
740+
},
741+
],
742+
},
743+
)
690744
})
691745

692746
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-object-types.test.ts

+79-36
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ describe(ruleName, () => {
252252
func<{ b: 'b'; a: 'aa' }>(/* ... */)
253253
`,
254254
output: dedent`
255-
func<{ a: 'aa'; b: 'b' }>(/* ... */)
255+
func<{ a: 'aa'; b: 'b'; }>(/* ... */)
256256
`,
257257
options: [options],
258258
errors: [
@@ -310,17 +310,6 @@ describe(ruleName, () => {
310310
}
311311
`,
312312
output: [
313-
dedent`
314-
type Type = {
315-
b: 'bb'
316-
a: 'aaa'
317-
c: 'c'
318-
d: {
319-
f: 'f'
320-
e: 'ee'
321-
}
322-
}
323-
`,
324313
dedent`
325314
type Type = {
326315
b: 'bb'
@@ -1018,6 +1007,82 @@ describe(ruleName, () => {
10181007
},
10191008
)
10201009
})
1010+
1011+
ruleTester.run(
1012+
`${ruleName}(${type}): sorts inline elements correctly`,
1013+
rule,
1014+
{
1015+
valid: [],
1016+
invalid: [
1017+
{
1018+
code: dedent`
1019+
type Type = {
1020+
b: string, a: string
1021+
}
1022+
`,
1023+
output: dedent`
1024+
type Type = {
1025+
a: string; b: string,
1026+
}
1027+
`,
1028+
options: [options],
1029+
errors: [
1030+
{
1031+
messageId: 'unexpectedObjectTypesOrder',
1032+
data: {
1033+
left: 'b',
1034+
right: 'a',
1035+
},
1036+
},
1037+
],
1038+
},
1039+
{
1040+
code: dedent`
1041+
type Type = {
1042+
b: string, a: string;
1043+
}
1044+
`,
1045+
output: dedent`
1046+
type Type = {
1047+
a: string; b: string,
1048+
}
1049+
`,
1050+
options: [options],
1051+
errors: [
1052+
{
1053+
messageId: 'unexpectedObjectTypesOrder',
1054+
data: {
1055+
left: 'b',
1056+
right: 'a',
1057+
},
1058+
},
1059+
],
1060+
},
1061+
{
1062+
code: dedent`
1063+
type Type = {
1064+
b: string, a: string,
1065+
}
1066+
`,
1067+
output: dedent`
1068+
type Type = {
1069+
a: string, b: string,
1070+
}
1071+
`,
1072+
options: [options],
1073+
errors: [
1074+
{
1075+
messageId: 'unexpectedObjectTypesOrder',
1076+
data: {
1077+
left: 'b',
1078+
right: 'a',
1079+
},
1080+
},
1081+
],
1082+
},
1083+
],
1084+
},
1085+
)
10211086
})
10221087

10231088
describe(`${ruleName}: sorting by natural order`, () => {
@@ -1256,7 +1321,7 @@ describe(ruleName, () => {
12561321
func<{ b: 'b'; a: 'aa' }>(/* ... */)
12571322
`,
12581323
output: dedent`
1259-
func<{ a: 'aa'; b: 'b' }>(/* ... */)
1324+
func<{ a: 'aa'; b: 'b'; }>(/* ... */)
12601325
`,
12611326
options: [options],
12621327
errors: [
@@ -1314,17 +1379,6 @@ describe(ruleName, () => {
13141379
}
13151380
`,
13161381
output: [
1317-
dedent`
1318-
type Type = {
1319-
b: 'bb'
1320-
a: 'aaa'
1321-
c: 'c'
1322-
d: {
1323-
f: 'f'
1324-
e: 'ee'
1325-
}
1326-
}
1327-
`,
13281382
dedent`
13291383
type Type = {
13301384
b: 'bb'
@@ -1850,7 +1904,7 @@ describe(ruleName, () => {
18501904
func<{ b: 'b'; a: 'aa' }>(/* ... */)
18511905
`,
18521906
output: dedent`
1853-
func<{ a: 'aa'; b: 'b' }>(/* ... */)
1907+
func<{ a: 'aa'; b: 'b'; }>(/* ... */)
18541908
`,
18551909
options: [options],
18561910
errors: [
@@ -1908,17 +1962,6 @@ describe(ruleName, () => {
19081962
}
19091963
`,
19101964
output: [
1911-
dedent`
1912-
type Type = {
1913-
b: 'bb'
1914-
a: 'aaa'
1915-
c: 'c'
1916-
d: {
1917-
f: 'f'
1918-
e: 'ee'
1919-
}
1920-
}
1921-
`,
19221965
dedent`
19231966
type Type = {
19241967
b: 'bb'

‎test/sort-objects.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -1775,6 +1775,60 @@ describe(ruleName, () => {
17751775
},
17761776
)
17771777
})
1778+
1779+
ruleTester.run(
1780+
`${ruleName}(${type}): sorts inline elements correctly`,
1781+
rule,
1782+
{
1783+
valid: [],
1784+
invalid: [
1785+
{
1786+
code: dedent`
1787+
let obj = {
1788+
b: string, a: string
1789+
}
1790+
`,
1791+
output: dedent`
1792+
let obj = {
1793+
a: string, b: string
1794+
}
1795+
`,
1796+
options: [options],
1797+
errors: [
1798+
{
1799+
messageId: 'unexpectedObjectsOrder',
1800+
data: {
1801+
left: 'b',
1802+
right: 'a',
1803+
},
1804+
},
1805+
],
1806+
},
1807+
{
1808+
code: dedent`
1809+
let obj = {
1810+
b: string, a: string,
1811+
}
1812+
`,
1813+
output: dedent`
1814+
let obj = {
1815+
a: string, b: string,
1816+
}
1817+
`,
1818+
options: [options],
1819+
errors: [
1820+
{
1821+
messageId: 'unexpectedObjectsOrder',
1822+
data: {
1823+
left: 'b',
1824+
right: 'a',
1825+
},
1826+
},
1827+
],
1828+
},
1829+
],
1830+
},
1831+
)
17781832
})
17791833

17801834
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-sets.test.ts

+54
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,60 @@ describe(ruleName, () => {
640640
invalid: [],
641641
},
642642
)
643+
644+
ruleTester.run(
645+
`${ruleName}(${type}): sorts inline elements correctly`,
646+
rule,
647+
{
648+
valid: [],
649+
invalid: [
650+
{
651+
code: dedent`
652+
new Set([
653+
b, a
654+
])
655+
`,
656+
output: dedent`
657+
new Set([
658+
a, b
659+
])
660+
`,
661+
options: [options],
662+
errors: [
663+
{
664+
messageId: 'unexpectedSetsOrder',
665+
data: {
666+
left: 'b',
667+
right: 'a',
668+
},
669+
},
670+
],
671+
},
672+
{
673+
code: dedent`
674+
new Set([
675+
b, a,
676+
])
677+
`,
678+
output: dedent`
679+
new Set([
680+
a, b,
681+
])
682+
`,
683+
options: [options],
684+
errors: [
685+
{
686+
messageId: 'unexpectedSetsOrder',
687+
data: {
688+
left: 'b',
689+
right: 'a',
690+
},
691+
},
692+
],
693+
},
694+
],
695+
},
696+
)
643697
})
644698

645699
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-switch-case.test.ts

+98
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,104 @@ describe(ruleName, () => {
705705
invalid: [],
706706
},
707707
)
708+
709+
ruleTester.run(
710+
`${ruleName}(${type}): sorts inline elements correctly`,
711+
rule,
712+
{
713+
valid: [],
714+
invalid: [
715+
{
716+
code: dedent`
717+
switch (x) {
718+
case "b": break; case "a": break
719+
}
720+
`,
721+
output: dedent`
722+
switch (x) {
723+
case "a": break; case "b": break;
724+
}
725+
`,
726+
options: [options],
727+
errors: [
728+
{
729+
messageId: 'unexpectedSwitchCaseOrder',
730+
data: {
731+
left: 'b',
732+
right: 'a',
733+
},
734+
},
735+
],
736+
},
737+
{
738+
code: dedent`
739+
switch (x) {
740+
case "b": break; case "a": break;
741+
}
742+
`,
743+
output: dedent`
744+
switch (x) {
745+
case "a": break; case "b": break;
746+
}
747+
`,
748+
options: [options],
749+
errors: [
750+
{
751+
messageId: 'unexpectedSwitchCaseOrder',
752+
data: {
753+
left: 'b',
754+
right: 'a',
755+
},
756+
},
757+
],
758+
},
759+
{
760+
code: dedent`
761+
switch (x) {
762+
case "b": { break } case "a": { break }
763+
}
764+
`,
765+
output: dedent`
766+
switch (x) {
767+
case "a": { break }; case "b": { break }
768+
}
769+
`,
770+
options: [options],
771+
errors: [
772+
{
773+
messageId: 'unexpectedSwitchCaseOrder',
774+
data: {
775+
left: 'b',
776+
right: 'a',
777+
},
778+
},
779+
],
780+
},
781+
{
782+
code: dedent`
783+
switch (x) {
784+
case "b": { break } case "a": { break };
785+
}
786+
`,
787+
output: dedent`
788+
switch (x) {
789+
case "a": { break }; case "b": { break }
790+
}
791+
`,
792+
options: [options],
793+
errors: [
794+
{
795+
messageId: 'unexpectedSwitchCaseOrder',
796+
data: {
797+
left: 'b',
798+
right: 'a',
799+
},
800+
},
801+
],
802+
},
803+
],
804+
},
805+
)
708806
})
709807

710808
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-union-types.test.ts

+50
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,56 @@ describe(ruleName, () => {
869869
},
870870
)
871871
})
872+
873+
ruleTester.run(
874+
`${ruleName}(${type}): sorts inline elements correctly`,
875+
rule,
876+
{
877+
valid: [],
878+
invalid: [
879+
{
880+
code: dedent`
881+
type T =
882+
| B | A
883+
`,
884+
output: dedent`
885+
type T =
886+
| A | B
887+
`,
888+
options: [options],
889+
errors: [
890+
{
891+
messageId: 'unexpectedUnionTypesOrder',
892+
data: {
893+
left: 'B',
894+
right: 'A',
895+
},
896+
},
897+
],
898+
},
899+
{
900+
code: dedent`
901+
type T =
902+
B | A
903+
`,
904+
output: dedent`
905+
type T =
906+
A | B
907+
`,
908+
options: [options],
909+
errors: [
910+
{
911+
messageId: 'unexpectedUnionTypesOrder',
912+
data: {
913+
left: 'B',
914+
right: 'A',
915+
},
916+
},
917+
],
918+
},
919+
],
920+
},
921+
)
872922
})
873923

874924
describe(`${ruleName}: sorting by natural order`, () => {

‎test/sort-variable-declarations.test.ts

+50
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,56 @@ describe(ruleName, () => {
919919
invalid: [],
920920
},
921921
)
922+
923+
ruleTester.run(
924+
`${ruleName}(${type}): sorts inline elements correctly`,
925+
rule,
926+
{
927+
valid: [],
928+
invalid: [
929+
{
930+
code: dedent`
931+
const
932+
b = 'b', a = 'a'
933+
`,
934+
output: dedent`
935+
const
936+
a = 'a', b = 'b'
937+
`,
938+
options: [options],
939+
errors: [
940+
{
941+
messageId: 'unexpectedVariableDeclarationsOrder',
942+
data: {
943+
left: 'b',
944+
right: 'a',
945+
},
946+
},
947+
],
948+
},
949+
{
950+
code: dedent`
951+
const
952+
b = 'b', a = 'a',
953+
`,
954+
output: dedent`
955+
const
956+
a = 'a', b = 'b',
957+
`,
958+
options: [options],
959+
errors: [
960+
{
961+
messageId: 'unexpectedVariableDeclarationsOrder',
962+
data: {
963+
left: 'b',
964+
right: 'a',
965+
},
966+
},
967+
],
968+
},
969+
],
970+
},
971+
)
922972
})
923973

924974
describe(`${ruleName}: sorting by natural order`, () => {

‎typings/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { TSESTree } from '@typescript-eslint/types'
22

33
export interface SortingNode<Node extends TSESTree.Node = TSESTree.Node> {
44
hasMultipleImportDeclarations?: boolean
5+
addSafetySemicolonWhenInline?: boolean
56
group?: string
67
name: string
78
size: number

‎utils/get-node-range.ts

-12
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ export let getNodeRange = (
1717
let start = node.range.at(0)!
1818
let end = node.range.at(1)!
1919

20-
let raw = sourceCode.text.slice(start, end)
21-
2220
if (ASTUtils.isParenthesized(node, sourceCode)) {
2321
let bodyOpeningParen = sourceCode.getTokenBefore(
2422
node,
@@ -34,16 +32,6 @@ export let getNodeRange = (
3432
end = bodyClosingParen.range.at(1)!
3533
}
3634

37-
if (raw.endsWith(';') || raw.endsWith(',')) {
38-
let tokensAfter = sourceCode.getTokensAfter(node, {
39-
includeComments: true,
40-
count: 2,
41-
})
42-
43-
if (node.loc.start.line === tokensAfter.at(1)?.loc.start.line) {
44-
end -= 1
45-
}
46-
}
4735
let comments = getCommentsBefore(node, sourceCode)
4836
let partitionComment = additionalOptions?.partitionByComment ?? false
4937
let partitionCommentMatcher = additionalOptions?.matcher ?? 'minimatch'

‎utils/make-fixes.ts

+36-13
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export let makeFixes = (
1010
fixer: TSESLint.RuleFixer,
1111
nodes: SortingNode[],
1212
sortedNodes: SortingNode[],
13-
source: TSESLint.SourceCode,
13+
sourceCode: TSESLint.SourceCode,
1414
additionalOptions?: {
1515
partitionByComment: string[] | boolean | string
1616
matcher: 'minimatch' | 'regex'
@@ -22,21 +22,44 @@ export let makeFixes = (
2222
nodes.at(0)?.node.loc.start.line === nodes.at(-1)?.node.loc.end.line
2323

2424
for (let max = nodes.length, i = 0; i < max; i++) {
25-
let { node } = nodes.at(i)!
25+
let sortingNode = nodes.at(i)!
26+
let sortedSortingNode = sortedNodes.at(i)!
27+
let { node } = sortingNode
28+
let { node: sortedNode } = sortedSortingNode
2629

27-
fixes.push(
28-
fixer.replaceTextRange(
29-
getNodeRange(node, source, additionalOptions),
30-
source.text.slice(
31-
...getNodeRange(sortedNodes.at(i)!.node, source, additionalOptions),
30+
if (node !== sortedNode) {
31+
let sortedNodeCode = sourceCode.text.slice(
32+
...getNodeRange(sortedNode, sourceCode, additionalOptions),
33+
)
34+
let sortedNodeText = sourceCode.getText(sortedNode)
35+
let tokensAfter = sourceCode.getTokensAfter(node, {
36+
includeComments: false,
37+
count: 1,
38+
})
39+
let nextToken = tokensAfter.at(0)
40+
if (
41+
!sortedNodeText.endsWith(';') &&
42+
!sortedNodeText.endsWith(',') &&
43+
sortedSortingNode.addSafetySemicolonWhenInline &&
44+
nextToken &&
45+
node.loc.start.line === nextToken.loc.start.line &&
46+
nextToken.value !== ';' &&
47+
nextToken.value !== ','
48+
) {
49+
sortedNodeCode += ';'
50+
}
51+
fixes.push(
52+
fixer.replaceTextRange(
53+
getNodeRange(node, sourceCode, additionalOptions),
54+
sortedNodeCode,
3255
),
33-
),
34-
)
56+
)
57+
}
3558

36-
let commentAfter = getCommentAfter(sortedNodes.at(i)!.node, source)
59+
let commentAfter = getCommentAfter(sortedNodes.at(i)!.node, sourceCode)
3760

3861
if (commentAfter && !isSingleline) {
39-
let tokenBefore = source.getTokenBefore(commentAfter)
62+
let tokenBefore = sourceCode.getTokenBefore(commentAfter)
4063

4164
let range: TSESTree.Range = [
4265
tokenBefore!.range.at(1)!,
@@ -45,14 +68,14 @@ export let makeFixes = (
4568

4669
fixes.push(fixer.replaceTextRange(range, ''))
4770

48-
let tokenAfterNode = source.getTokenAfter(node)
71+
let tokenAfterNode = sourceCode.getTokenAfter(node)
4972

5073
fixes.push(
5174
fixer.insertTextAfter(
5275
tokenAfterNode?.loc.end.line === node.loc.end.line
5376
? tokenAfterNode
5477
: node,
55-
source.text.slice(...range),
78+
sourceCode.text.slice(...range),
5679
),
5780
)
5881
}

‎utils/range-to-diff.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import type { TSESTree } from '@typescript-eslint/types'
2+
import type { TSESLint } from '@typescript-eslint/utils'
23

3-
export let rangeToDiff = (range: TSESTree.Range): number => {
4-
let [from, to] = range
5-
return to - from
4+
export let rangeToDiff = (
5+
node: TSESTree.Node,
6+
sourceCode: TSESLint.SourceCode,
7+
): number => {
8+
let nodeText = sourceCode.getText(node)
9+
let endsWithCommaOrSemicolon =
10+
nodeText.endsWith(';') || nodeText.endsWith(',')
11+
let [from, to] = node.range
12+
return to - from - (endsWithCommaOrSemicolon ? 1 : 0)
613
}

0 commit comments

Comments
 (0)
Please sign in to comment.