Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 15 additions & 86 deletions src/rules/prefer-array-fill.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,84 +62,49 @@ ruleTester.run('prefer-array-fill', preferArrayFill, {
{
code: 'const arr = Array.from({length: 5}, () => 0)',
output: 'const arr = Array.from({length: 5}).fill(0)',
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: '5', value: '0'}
}
]
errors: [{messageId: 'preferFillArrayFrom'}]
},

// Array.from with string value
{
code: 'const arr = Array.from({length: 3}, () => "test")',
output: 'const arr = Array.from({length: 3}).fill("test")',
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: '3', value: '"test"'}
}
]
errors: [{messageId: 'preferFillArrayFrom'}]
},

// Array.from with expression in length
{
code: 'const arr = Array.from({length: 2 + 3}, () => 0)',
output: 'const arr = Array.from({length: 2 + 3}).fill(0)',
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: '2 + 3', value: '0'}
}
]
errors: [{messageId: 'preferFillArrayFrom'}]
},

// Array.from with regular function expression
{
code: 'const arr = Array.from({length: 5}, function() { return 0 })',
output: 'const arr = Array.from({length: 5}).fill(0)',
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: '5', value: '0'}
}
]
errors: [{messageId: 'preferFillArrayFrom'}]
},

// Spread Array with map and arrow function
{
code: 'const arr = [...Array(5)].map(() => 0)',
output: 'const arr = Array(5).fill(0)',
errors: [
{
messageId: 'preferFillSpreadMap',
data: {length: '5', value: '0'}
}
]
errors: [{messageId: 'preferFillSpreadMap'}]
},

// Spread Array with map and string value
{
code: 'const arr = [...Array(3)].map(() => "test")',
output: 'const arr = Array(3).fill("test")',
errors: [
{
messageId: 'preferFillSpreadMap',
data: {length: '3', value: '"test"'}
}
]
errors: [{messageId: 'preferFillSpreadMap'}]
},

// Spread Array with map and function expression
{
code: 'const arr = [...Array(5)].map(function() { return 1 })',
output: 'const arr = Array(5).fill(1)',
errors: [
{
messageId: 'preferFillSpreadMap',
data: {length: '5', value: '1'}
}
]
errors: [{messageId: 'preferFillSpreadMap'}]
},

// Multiple occurrences
Expand All @@ -149,87 +114,51 @@ const arr2 = [...Array(3)].map(() => "test");`,
output: `const arr1 = Array.from({length: 5}).fill(0);
const arr2 = Array(3).fill("test");`,
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: '5', value: '0'}
},
{
messageId: 'preferFillSpreadMap',
data: {length: '3', value: '"test"'}
}
{messageId: 'preferFillArrayFrom'},
{messageId: 'preferFillSpreadMap'}
]
},

// Used in expressions
{
code: 'console.log(Array.from({length: 5}, () => 0))',
output: 'console.log(Array.from({length: 5}).fill(0))',
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: '5', value: '0'}
}
]
errors: [{messageId: 'preferFillArrayFrom'}]
},

// Used in return statements
{
code: 'function getArray() { return [...Array(5)].map(() => 0) }',
output: 'function getArray() { return Array(5).fill(0) }',
errors: [
{
messageId: 'preferFillSpreadMap',
data: {length: '5', value: '0'}
}
]
errors: [{messageId: 'preferFillSpreadMap'}]
},

// Variable length
{
code: 'const arr = Array.from({length: n}, () => 0)',
output: 'const arr = Array.from({length: n}).fill(0)',
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: 'n', value: '0'}
}
]
errors: [{messageId: 'preferFillArrayFrom'}]
},

// Complex expressions in value
{
code: 'const arr = [...Array(5)].map(() => 1 + 2)',
output: 'const arr = Array(5).fill(1 + 2)',
errors: [
{
messageId: 'preferFillSpreadMap',
data: {length: '5', value: '1 + 2'}
}
]
errors: [{messageId: 'preferFillSpreadMap'}]
},

// Logical expression with all-constant operands
{
code: 'const arr = Array.from({length: 5}, () => a ?? b)',
output: 'const arr = Array.from({length: 5}).fill(a ?? b)',
errors: [
{
messageId: 'preferFillArrayFrom',
data: {length: '5', value: 'a ?? b'}
}
]
errors: [{messageId: 'preferFillArrayFrom'}]
},

// Conditional expression with all-constant branches
{
code: 'const arr = [...Array(5)].map(() => a ? b : c)',
output: 'const arr = Array(5).fill(a ? b : c)',
errors: [
{
messageId: 'preferFillSpreadMap',
data: {length: '5', value: 'a ? b : c'}
}
]
errors: [{messageId: 'preferFillSpreadMap'}]
}
]
});
12 changes: 2 additions & 10 deletions src/rules/prefer-array-fill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ export const preferArrayFill: Rule.RuleModule = {
schema: [],
messages: {
preferFillArrayFrom:
'Use Array.from({length: {{length}}}).fill({{value}}) instead of Array.from with a constant callback',
'Use `Array.from({length: n}).fill(value)` instead of `Array.from` with a constant callback',
preferFillSpreadMap:
'Use Array({{length}}).fill({{value}}) instead of spread Array with map'
'Use `Array(n).fill(value)` instead of spreading `Array(n)` and mapping'
}
},
create(context) {
Expand Down Expand Up @@ -139,10 +139,6 @@ export const preferArrayFill: Rule.RuleModule = {
context.report({
node,
messageId: 'preferFillArrayFrom',
data: {
length: lengthText,
value: valueText
},
fix(fixer) {
return fixer.replaceText(
node,
Expand Down Expand Up @@ -195,10 +191,6 @@ export const preferArrayFill: Rule.RuleModule = {
context.report({
node,
messageId: 'preferFillSpreadMap',
data: {
length: lengthText,
value: valueText
},
fix(fixer) {
return fixer.replaceText(
node,
Expand Down
81 changes: 11 additions & 70 deletions src/rules/prefer-array-from-map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,48 +48,28 @@ ruleTester.run('prefer-array-from-map', preferArrayFromMap, {
{
code: 'const result = [...arr].map(x => x * 2)',
output: 'const result = Array.from(arr, x => x * 2)',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'arr', mapper: 'x => x * 2'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// With named function
{
code: 'const result = [...items].map(double)',
output: 'const result = Array.from(items, double)',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'items', mapper: 'double'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// With function expression
{
code: 'const result = [...list].map(function(x) { return x * 2 })',
output: 'const result = Array.from(list, function(x) { return x * 2 })',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'list', mapper: 'function(x) { return x * 2 }'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// With method call on iterable
{
code: 'const result = [...map.values()].map(process)',
output: 'const result = Array.from(map.values(), process)',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'map.values()', mapper: 'process'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// Multiple occurrences
Expand All @@ -98,90 +78,51 @@ ruleTester.run('prefer-array-from-map', preferArrayFromMap, {
const b = [...arr2].map(y => y + 1)`,
output: `const a = Array.from(arr1, x => x * 2)
const b = Array.from(arr2, y => y + 1)`,
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'arr1', mapper: 'x => x * 2'}
},
{
messageId: 'preferArrayFrom',
data: {iterable: 'arr2', mapper: 'y => y + 1'}
}
]
errors: [{messageId: 'preferArrayFrom'}, {messageId: 'preferArrayFrom'}]
},

// Used in return statement
{
code: 'function transform(items) { return [...items].map(x => x * 2) }',
output:
'function transform(items) { return Array.from(items, x => x * 2) }',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'items', mapper: 'x => x * 2'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// Used in expression
{
code: 'console.log([...data].map(format))',
output: 'console.log(Array.from(data, format))',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'data', mapper: 'format'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// Complex iterable expression
{
code: 'const result = [...getItems()].map(x => x.id)',
output: 'const result = Array.from(getItems(), x => x.id)',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'getItems()', mapper: 'x => x.id'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// With member expression
{
code: 'const result = [...this.items].map(process)',
output: 'const result = Array.from(this.items, process)',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'this.items', mapper: 'process'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// Chained with other array methods
{
code: 'const doubled = [...numbers].map(n => n * 2).filter(n => n > 10)',
output:
'const doubled = Array.from(numbers, n => n * 2).filter(n => n > 10)',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: 'numbers', mapper: 'n => n * 2'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
},

// sequence expressions must stay parenthesised
{
code: 'const result = [...(a, items)].map(process)',
output: 'const result = Array.from((a, items), process)',
errors: [
{
messageId: 'preferArrayFrom',
data: {iterable: '(a, items)', mapper: 'process'}
}
]
errors: [{messageId: 'preferArrayFrom'}]
}
]
});
6 changes: 1 addition & 5 deletions src/rules/prefer-array-from-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const preferArrayFromMap: Rule.RuleModule = {
schema: [],
messages: {
preferArrayFrom:
'Use Array.from({{iterable}}, {{mapper}}) instead of [...{{iterable}}].map({{mapper}}) to avoid creating an intermediate array'
'Use `Array.from(iterable, fn)` instead of `[...iterable].map(fn)` to avoid creating an intermediate array.'
}
},
create(context) {
Expand Down Expand Up @@ -81,10 +81,6 @@ export const preferArrayFromMap: Rule.RuleModule = {
context.report({
node,
messageId: 'preferArrayFrom',
data: {
iterable: iterableText,
mapper: mapperText
},
fix(fixer) {
return fixer.replaceText(
node,
Expand Down
Loading
Loading