164 lines
2.5 KiB
TypeScript
164 lines
2.5 KiB
TypeScript
|
import ist from "ist"
|
||
|
import {EditorState, IndentContext} from "@codemirror/next/state"
|
||
|
import {javascript} from "@codemirror/next/lang-javascript"
|
||
|
|
||
|
function getIndent(state: EditorState, pos: number): number {
|
||
|
for (let f of state.facet(EditorState.indentation)) {
|
||
|
let result = f(new IndentContext(state), pos)
|
||
|
if (result > -1) return result
|
||
|
}
|
||
|
return -1
|
||
|
}
|
||
|
|
||
|
function check(code: string) {
|
||
|
return () => {
|
||
|
code = /^\n*([^]*)/.exec(code)![1]
|
||
|
let state = EditorState.create({doc: code, extensions: [javascript()]})
|
||
|
for (let pos = 0, lines = code.split("\n"), i = 0; i < lines.length; i++) {
|
||
|
let line = lines[i], indent = /^\s*/.exec(line)![0].length
|
||
|
ist(`${getIndent(state, pos)} (${i + 1})`, `${indent} (${i + 1})`)
|
||
|
pos += line.length + 1
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
describe("javascript indentation", () => {
|
||
|
it("indents argument blocks", check(`
|
||
|
foo({
|
||
|
bar,
|
||
|
baz
|
||
|
})
|
||
|
`))
|
||
|
|
||
|
it("indents function args", check(`
|
||
|
foo(
|
||
|
bar
|
||
|
)`))
|
||
|
|
||
|
it("indents nested calls", check(`
|
||
|
one(
|
||
|
two(
|
||
|
three(
|
||
|
four()
|
||
|
)
|
||
|
)
|
||
|
)`))
|
||
|
|
||
|
it("aligns lists", check(`
|
||
|
one(two,
|
||
|
three({four: five,
|
||
|
six: seven
|
||
|
}))`))
|
||
|
|
||
|
it("indents unfinished nodes", check(`
|
||
|
if (foo &&
|
||
|
`))
|
||
|
|
||
|
it("deindents else", check(`
|
||
|
if (1)
|
||
|
a
|
||
|
else
|
||
|
b
|
||
|
`))
|
||
|
|
||
|
it("support multiple opening calls on a line", check(`
|
||
|
foo(bar(baz(
|
||
|
ugh(quux(
|
||
|
blah)))))
|
||
|
`))
|
||
|
|
||
|
it("supports opening brackets on their own line", check(`
|
||
|
const something =
|
||
|
[
|
||
|
a,
|
||
|
b
|
||
|
]
|
||
|
`))
|
||
|
|
||
|
it("handles hanging braces", check(`
|
||
|
function foo()
|
||
|
{
|
||
|
body()
|
||
|
}
|
||
|
`))
|
||
|
|
||
|
it("indents case bodies", check(`
|
||
|
switch (1) {
|
||
|
case 22:
|
||
|
console.log(2)
|
||
|
break
|
||
|
default:
|
||
|
return 2
|
||
|
}`))
|
||
|
|
||
|
it("indents method chains", check(`
|
||
|
return blah
|
||
|
.something()
|
||
|
.anotherOne(
|
||
|
withArguments
|
||
|
)
|
||
|
.catch(x)
|
||
|
`))
|
||
|
|
||
|
it("indents JSON-style", check(`
|
||
|
let j = {
|
||
|
foo: [
|
||
|
{
|
||
|
1: true,
|
||
|
2: false
|
||
|
},
|
||
|
{},
|
||
|
],
|
||
|
quux: null
|
||
|
}
|
||
|
`))
|
||
|
|
||
|
it("indents continued properties", check(`
|
||
|
let o = {
|
||
|
foo: 1 + 3 +
|
||
|
4,
|
||
|
bar: 11
|
||
|
}
|
||
|
`))
|
||
|
|
||
|
it("doesn't get confused by continued param lists", check(`
|
||
|
function foo(a, b,
|
||
|
c, d) {
|
||
|
return
|
||
|
}
|
||
|
`))
|
||
|
|
||
|
it("doesn't indent below labels", check(`
|
||
|
abc:
|
||
|
foo()
|
||
|
`))
|
||
|
|
||
|
it("properly indents function expression arguments", check(`
|
||
|
foo(100, function() {
|
||
|
return 2
|
||
|
})
|
||
|
`))
|
||
|
|
||
|
it("indents arrow functions", check(`
|
||
|
let x = a => {
|
||
|
return 4
|
||
|
}
|
||
|
let y = a =>
|
||
|
6
|
||
|
let x = (a,
|
||
|
b) =>
|
||
|
6
|
||
|
`))
|
||
|
|
||
|
it("indents braceless structure", check(`
|
||
|
for (;;)
|
||
|
if (0)
|
||
|
if (1)
|
||
|
foo()
|
||
|
else
|
||
|
bar()
|
||
|
else
|
||
|
baz()
|
||
|
`))
|
||
|
})
|