Skip to content

Commit 017bb93

Browse files
committed
Use a syntax node prop to wire up stream language indent logic
FIX: Call stream language indent functions even when the language is used as a nested parser. Closes codemirror/dev#1474
1 parent 396019f commit 017bb93

File tree

1 file changed

+19
-18
lines changed

1 file changed

+19
-18
lines changed

src/stream-parser.ts

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import {Tree, Input, TreeFragment, NodeType, NodeSet, SyntaxNode, PartialParse, Parser, NodeProp} from "@lezer/common"
1+
import {Tree, Input, TreeFragment, NodeType, NodeSet, PartialParse, Parser, NodeProp} from "@lezer/common"
22
import {Tag, tags as highlightTags, styleTags} from "@lezer/highlight"
33
import {EditorState, Facet} from "@codemirror/state"
4-
import {Language, defineLanguageFacet, languageDataProp, syntaxTree, ParseContext} from "./language"
5-
import {IndentContext, indentService, getIndentUnit} from "./indent"
4+
import {Language, defineLanguageFacet, languageDataProp, ParseContext} from "./language"
5+
import {TreeIndentContext, IndentContext, indentNodeProp, getIndentUnit} from "./indent"
66
import {StringStream} from "./stringstream"
77

88
export {StringStream}
@@ -94,8 +94,8 @@ export class StreamLanguage<State> extends Language {
9494
return new Parse(self, input, fragments, ranges)
9595
}
9696
}
97-
super(data, impl, [indentService.of((cx, pos) => this.getIndent(cx, pos))], parser.name)
98-
this.topNode = docID(data)
97+
super(data, impl, [], parser.name)
98+
this.topNode = docID(data, this)
9999
self = this
100100
this.streamParser = p
101101
this.stateAfter = new NodeProp<State>({perNode: true})
@@ -105,22 +105,20 @@ export class StreamLanguage<State> extends Language {
105105
/// Define a stream language.
106106
static define<State>(spec: StreamParser<State>) { return new StreamLanguage(spec) }
107107

108-
private getIndent(cx: IndentContext, pos: number) {
109-
let tree = syntaxTree(cx.state), at: SyntaxNode | null = tree.resolve(pos)
110-
while (at && at.type != this.topNode) at = at.parent
111-
if (!at) return null
108+
/// @internal
109+
getIndent(cx: TreeIndentContext) {
112110
let from = undefined
113111
let {overrideIndentation} = cx.options
114112
if (overrideIndentation) {
115113
from = IndentedFrom.get(cx.state)
116-
if (from != null && from < pos - 1e4) from = undefined
114+
if (from != null && from < cx.pos - 1e4) from = undefined
117115
}
118-
let start = findState(this, tree, 0, at.from, from ?? pos), statePos, state
116+
let start = findState(this, cx.node.tree!, 0, cx.node.from, from ?? cx.pos), statePos, state
119117
if (start) { state = start.state; statePos = start.pos + 1 }
120118
else { state = this.streamParser.startState(cx.unit) ; statePos = 0 }
121-
if (pos - statePos > C.MaxIndentScanDist) return null
122-
while (statePos < pos) {
123-
let line = cx.state.doc.lineAt(statePos), end = Math.min(pos, line.to)
119+
if (cx.pos - statePos > C.MaxIndentScanDist) return null
120+
while (statePos < cx.pos) {
121+
let line = cx.state.doc.lineAt(statePos), end = Math.min(cx.pos, line.to)
124122
if (line.length) {
125123
let indentation = overrideIndentation ? overrideIndentation(line.from) : -1
126124
let stream = new StringStream(line.text, cx.state.tabSize, cx.unit, indentation < 0 ? undefined : indentation)
@@ -129,10 +127,10 @@ export class StreamLanguage<State> extends Language {
129127
} else {
130128
this.streamParser.blankLine(state, cx.unit)
131129
}
132-
if (end == pos) break
130+
if (end == cx.pos) break
133131
statePos = line.to + 1
134132
}
135-
let line = cx.lineAt(pos)
133+
let line = cx.lineAt(cx.pos)
136134
if (overrideIndentation && from == null) IndentedFrom.set(cx.state, line.from)
137135
return this.streamParser.indent(state, /^\s*(.*)/.exec(line.text)![1], cx)
138136
}
@@ -424,8 +422,11 @@ function createTokenType(extra: {[name: string]: Tag | readonly Tag[]}, tagStr:
424422
return type.id
425423
}
426424

427-
function docID(data: Facet<{[name: string]: any}>) {
428-
let type = NodeType.define({id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true})
425+
function docID(data: Facet<{[name: string]: any}>, lang: StreamLanguage<unknown>) {
426+
let type = NodeType.define({id: typeArray.length, name: "Document", props: [
427+
languageDataProp.add(() => data),
428+
indentNodeProp.add(() => cx => lang.getIndent(cx))
429+
], top: true})
429430
typeArray.push(type)
430431
return type
431432
}

0 commit comments

Comments
 (0)