fixed name declared twice

This commit is contained in:
Dmitry Vasilev
2023-10-27 12:39:25 +08:00
parent aafefe1159
commit 487ec28b1c
3 changed files with 75 additions and 10 deletions

View File

@@ -1,7 +1,9 @@
// TODO rename to analyze.js
import {set_push, set_diff, set_union, map_object, map_find, uniq} from './utils.js'
import {collect_destructuring_identifiers, collect_imports, ancestry, find_leaf} from './ast_utils.js'
import {set_push, set_diff, set_union, map_object, map_find, uniq, uniq_by}
from './utils.js'
import {collect_destructuring_identifiers, collect_imports, ancestry, find_leaf}
from './ast_utils.js'
const map_find_definitions = (nodes, mapper) => {
const result = nodes.map(mapper)
@@ -305,9 +307,27 @@ const analyze_await = (node, is_async_context = true) => {
return result ?? []
}
const find_duplicates = names => {
const duplicates = names.filter((n, i) =>
names.find((name, j) => name.value == n.value && j < i) != null
)
const problems = duplicates.map(d => ({
index: d.index,
length: d.length,
message: `Identifier '${d.value}' has already been declared`,
}))
return problems
}
const named_declared_once = node => {
return collect_problems(node, null, (node, cxt) => {
if(node.type == 'do') {
if(node.type == 'function_expr') {
const names = collect_destructuring_identifiers(node.function_args)
return {
context: uniq_by(names, n => n.value),
problems: find_duplicates(names),
}
} else if(node.type == 'do') {
const names = node
.children
.map(c => {
@@ -327,14 +347,9 @@ const named_declared_once = node => {
})
.flat()
.filter(n => n != null)
const duplicates = names.filter((n, i) =>
names.find((name, j) => name.value == n.value && j < i) != null
const problems = find_duplicates(
[...(cxt ?? []), ...names]
)
const problems = duplicates.map(d => ({
index: d.index,
length: d.length,
message: `Identifier '${d.value}' has already been declared`,
}))
return {context: null, problems}
} else {
return {context: null, problems: null}

View File

@@ -53,6 +53,13 @@ export const zip = (x,y) => {
export const uniq = arr => [...new Set(arr)]
export const uniq_by = (arr, mapper) => [
...new Map(
arr.map(e => [mapper(e), e])
)
.values()
]
export const collect_nodes_with_parents = new Function('node', 'pred', `
const result = []

View File

@@ -1269,6 +1269,49 @@ export const tests = [
]
)
}),
test('identifier has already been declared in fn arg', () => {
const code = `
function foo(x) {
const x = 1
}
`
const i = test_initial_state(code)
assert_equal(i.parse_result.ok, false)
assert_equal(
i.parse_result.problems,
[
{
index: code.indexOf('x = 1'),
length: 1,
message: "Identifier 'x' has already been declared",
module: '',
}
]
)
}),
test('identifier has been declared twice in args', () => {
const code = `
function foo({x,x}) {
}
`
const i = test_initial_state(code)
assert_equal(i.parse_result.ok, false)
assert_equal(
i.parse_result.problems,
[
{
index: code.indexOf('x}'),
length: 1,
message: "Identifier 'x' has already been declared",
module: '',
}
]
)
}),
test('identifier has already been declared fn decl', () => {
const code = `