plugin fixes: incorrect reformatting on }, incorrect parsing of class minidocs
This commit is contained in:
parent
1d9befe101
commit
9e138367ef
@ -1773,10 +1773,11 @@ class Compiler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun parseEnumDeclaration(): Statement {
|
private fun parseEnumDeclaration(): Statement {
|
||||||
val startPos = pendingDeclStart ?: cc.currentPos()
|
val nameToken = cc.requireToken(Token.Type.ID)
|
||||||
|
val startPos = pendingDeclStart ?: nameToken.pos
|
||||||
val doc = pendingDeclDoc ?: consumePendingDoc()
|
val doc = pendingDeclDoc ?: consumePendingDoc()
|
||||||
pendingDeclDoc = null
|
pendingDeclDoc = null
|
||||||
val nameToken = cc.requireToken(Token.Type.ID)
|
pendingDeclStart = null
|
||||||
// so far only simplest enums:
|
// so far only simplest enums:
|
||||||
val names = mutableListOf<String>()
|
val names = mutableListOf<String>()
|
||||||
// skip '{'
|
// skip '{'
|
||||||
@ -1822,6 +1823,10 @@ class Compiler(
|
|||||||
|
|
||||||
private suspend fun parseClassDeclaration(): Statement {
|
private suspend fun parseClassDeclaration(): Statement {
|
||||||
val nameToken = cc.requireToken(Token.Type.ID)
|
val nameToken = cc.requireToken(Token.Type.ID)
|
||||||
|
val startPos = pendingDeclStart ?: nameToken.pos
|
||||||
|
val doc = pendingDeclDoc ?: consumePendingDoc()
|
||||||
|
pendingDeclDoc = null
|
||||||
|
pendingDeclStart = null
|
||||||
return inCodeContext(CodeContext.ClassBody(nameToken.value)) {
|
return inCodeContext(CodeContext.ClassBody(nameToken.value)) {
|
||||||
val constructorArgsDeclaration =
|
val constructorArgsDeclaration =
|
||||||
if (cc.skipTokenOfType(Token.Type.LPAREN, isOptional = true))
|
if (cc.skipTokenOfType(Token.Type.LPAREN, isOptional = true))
|
||||||
@ -1879,7 +1884,7 @@ class Compiler(
|
|||||||
|
|
||||||
// Emit MiniClassDecl with collected base names; bodyRange is omitted for now
|
// Emit MiniClassDecl with collected base names; bodyRange is omitted for now
|
||||||
run {
|
run {
|
||||||
val declRange = MiniRange(pendingDeclStart ?: nameToken.pos, cc.currentPos())
|
val declRange = MiniRange(startPos, cc.currentPos())
|
||||||
val bases = baseSpecs.map { it.name }
|
val bases = baseSpecs.map { it.name }
|
||||||
// Collect constructor fields declared as val/var in primary constructor
|
// Collect constructor fields declared as val/var in primary constructor
|
||||||
val ctorFields = mutableListOf<MiniCtorField>()
|
val ctorFields = mutableListOf<MiniCtorField>()
|
||||||
@ -1903,11 +1908,10 @@ class Compiler(
|
|||||||
bases = bases,
|
bases = bases,
|
||||||
bodyRange = classBodyRange,
|
bodyRange = classBodyRange,
|
||||||
ctorFields = ctorFields,
|
ctorFields = ctorFields,
|
||||||
doc = pendingDeclDoc,
|
doc = doc,
|
||||||
nameStart = nameToken.pos
|
nameStart = nameToken.pos
|
||||||
)
|
)
|
||||||
miniSink?.onClassDecl(node)
|
miniSink?.onClassDecl(node)
|
||||||
pendingDeclDoc = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val initScope = popInitScope()
|
val initScope = popInitScope()
|
||||||
|
|||||||
@ -288,7 +288,20 @@ object LyngFormatter {
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
// Normalize collected base indent: replace tabs with spaces
|
// Normalize collected base indent: replace tabs with spaces
|
||||||
var baseIndent = if (onlyWs) base.toString().replace("\t", " ".repeat(config.indentSize)) else ""
|
var baseIndent = if (onlyWs) {
|
||||||
|
if (start == lineStart) {
|
||||||
|
// Range starts at line start, pick up this line's indentation as base
|
||||||
|
var k = start
|
||||||
|
val lineIndent = StringBuilder()
|
||||||
|
while (k < text.length && text[k] != '\n' && (text[k] == ' ' || text[k] == '\t')) {
|
||||||
|
lineIndent.append(text[k])
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
lineIndent.toString().replace("\t", " ".repeat(config.indentSize))
|
||||||
|
} else {
|
||||||
|
base.toString().replace("\t", " ".repeat(config.indentSize))
|
||||||
|
}
|
||||||
|
} else ""
|
||||||
var parentBaseIndent: String? = baseIndent
|
var parentBaseIndent: String? = baseIndent
|
||||||
if (baseIndent.isEmpty()) {
|
if (baseIndent.isEmpty()) {
|
||||||
// Fallback: use the indent of the nearest previous non-empty line as base.
|
// Fallback: use the indent of the nearest previous non-empty line as base.
|
||||||
|
|||||||
@ -115,6 +115,23 @@ class MiniAstTest {
|
|||||||
assertNotNull(vd.initRange)
|
assertNotNull(vd.initRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun miniAst_captures_class_doc_with_members() = runTest {
|
||||||
|
val code = """
|
||||||
|
/** Class C docs */
|
||||||
|
class C {
|
||||||
|
fun foo() {}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
val (_, sink) = compileWithMini(code)
|
||||||
|
val mini = sink.build()
|
||||||
|
assertNotNull(mini)
|
||||||
|
val cd = mini!!.declarations.filterIsInstance<MiniClassDecl>().firstOrNull { it.name == "C" }
|
||||||
|
assertNotNull(cd)
|
||||||
|
assertNotNull(cd.doc, "Class doc should be preserved even with members")
|
||||||
|
assertTrue(cd.doc!!.raw.contains("Class C docs"))
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun miniAst_captures_class_bases_and_doc() = runTest {
|
fun miniAst_captures_class_bases_and_doc() = runTest {
|
||||||
val code = """
|
val code = """
|
||||||
|
|||||||
@ -434,4 +434,37 @@ class BlockReindentTest {
|
|||||||
kotlin.test.assertTrue(lines.getOrNull(innerStart + 1)?.trimStart()?.startsWith("1") == true)
|
kotlin.test.assertTrue(lines.getOrNull(innerStart + 1)?.trimStart()?.startsWith("1") == true)
|
||||||
kotlin.test.assertEquals("}", lines.getOrNull(innerStart + 2)?.trim())
|
kotlin.test.assertEquals("}", lines.getOrNull(innerStart + 2)?.trim())
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
fun reindentRange_doubledIndentationFix() {
|
||||||
|
val src = """
|
||||||
|
class X {
|
||||||
|
fun funA(): String {
|
||||||
|
"a"
|
||||||
|
}
|
||||||
|
fun runB() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
// The range for runB should be from the start of 'fun runB' line to the end of '}' line.
|
||||||
|
val startOfRunB = src.indexOf(" fun runB")
|
||||||
|
val endOfRunB = src.indexOf(" }") + " }".length
|
||||||
|
val range = startOfRunB until endOfRunB
|
||||||
|
|
||||||
|
val cfg = LyngFormatConfig(indentSize = 4)
|
||||||
|
val updated = LyngFormatter.reindentRange(src, range, cfg, preserveBaseIndent = true)
|
||||||
|
|
||||||
|
val expected = """
|
||||||
|
class X {
|
||||||
|
fun funA(): String {
|
||||||
|
"a"
|
||||||
|
}
|
||||||
|
fun runB() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
assertEquals(expected, updated)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user