mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 21:14:28 -08:00
fixed name declared twice
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
// TODO rename to analyze.js
|
// TODO rename to analyze.js
|
||||||
|
|
||||||
import {set_push, set_diff, set_union, map_object, map_find, uniq} from './utils.js'
|
import {set_push, set_diff, set_union, map_object, map_find, uniq, uniq_by}
|
||||||
import {collect_destructuring_identifiers, collect_imports, ancestry, find_leaf} from './ast_utils.js'
|
from './utils.js'
|
||||||
|
import {collect_destructuring_identifiers, collect_imports, ancestry, find_leaf}
|
||||||
|
from './ast_utils.js'
|
||||||
|
|
||||||
const map_find_definitions = (nodes, mapper) => {
|
const map_find_definitions = (nodes, mapper) => {
|
||||||
const result = nodes.map(mapper)
|
const result = nodes.map(mapper)
|
||||||
@@ -305,9 +307,27 @@ const analyze_await = (node, is_async_context = true) => {
|
|||||||
return result ?? []
|
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 => {
|
const named_declared_once = node => {
|
||||||
return collect_problems(node, null, (node, cxt) => {
|
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
|
const names = node
|
||||||
.children
|
.children
|
||||||
.map(c => {
|
.map(c => {
|
||||||
@@ -327,14 +347,9 @@ const named_declared_once = node => {
|
|||||||
})
|
})
|
||||||
.flat()
|
.flat()
|
||||||
.filter(n => n != null)
|
.filter(n => n != null)
|
||||||
const duplicates = names.filter((n, i) =>
|
const problems = find_duplicates(
|
||||||
names.find((name, j) => name.value == n.value && j < i) != null
|
[...(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}
|
return {context: null, problems}
|
||||||
} else {
|
} else {
|
||||||
return {context: null, problems: null}
|
return {context: null, problems: null}
|
||||||
|
|||||||
@@ -53,6 +53,13 @@ export const zip = (x,y) => {
|
|||||||
|
|
||||||
export const uniq = arr => [...new Set(arr)]
|
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', `
|
export const collect_nodes_with_parents = new Function('node', 'pred', `
|
||||||
const result = []
|
const result = []
|
||||||
|
|
||||||
|
|||||||
43
test/test.js
43
test/test.js
@@ -1270,6 +1270,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', () => {
|
test('identifier has already been declared fn decl', () => {
|
||||||
const code = `
|
const code = `
|
||||||
const x = 1
|
const x = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user