Refactor FIR diagnostics: cleanup and extract position finder
for reusing the latter in the inliner for LT-based sources
This commit is contained in:
@@ -14,6 +14,9 @@ import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import java.io.InputStreamReader
|
||||
|
||||
sealed class KtSourceElementKind
|
||||
|
||||
@@ -440,3 +443,91 @@ inline fun LighterASTNode.toKtLightSourceElement(
|
||||
startOffset: Int = this.startOffset,
|
||||
endOffset: Int = this.endOffset
|
||||
): KtLightSourceElement = KtLightSourceElement(this, startOffset, endOffset, tree, kind)
|
||||
|
||||
|
||||
class KtSourceFilePosition(val line: Int, val column: Int, val lineContent: String?) {
|
||||
|
||||
// NOTE: This method is used for presenting positions to the user
|
||||
override fun toString(): String = if (line < 0) "(offset: $column line unknown)" else "($line,$column)"
|
||||
|
||||
companion object {
|
||||
val NONE = KtSourceFilePosition(-1, -1, null)
|
||||
}
|
||||
}
|
||||
|
||||
class SequentialFilePositionFinder(file: File) : Closeable {
|
||||
|
||||
private var reader: InputStreamReader = file.reader(/* TODO: select proper charset */)
|
||||
|
||||
private var currentLineContent: String? = null
|
||||
private val buffer = CharArray(255)
|
||||
private var bufLength = -1
|
||||
private var bufPos = 0
|
||||
private var endOfStream = false
|
||||
private var skipNextLf = false
|
||||
|
||||
private var charsRead = 0
|
||||
private var currentLine = 0
|
||||
|
||||
// assuming that if called multiple times, calls should be sorted by ascending offset
|
||||
fun findNextPosition(offset: Int, withLineContents: Boolean = true): KtSourceFilePosition {
|
||||
assert(offset >= charsRead - (currentLineContent?.length ?: 0))
|
||||
|
||||
fun posInCurrentLine(): KtSourceFilePosition? {
|
||||
val col = offset - (charsRead - currentLineContent!!.length - 1)/* beginning of line offset */ + 1 /* col is 1-based */
|
||||
return if (col <= currentLineContent!!.length)
|
||||
KtSourceFilePosition(currentLine, col, if (withLineContents) currentLineContent else null)
|
||||
else null
|
||||
}
|
||||
|
||||
if (offset < charsRead) {
|
||||
return posInCurrentLine()!!
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (currentLineContent == null) {
|
||||
currentLineContent = readNextLine()
|
||||
}
|
||||
|
||||
posInCurrentLine()?.let { return@findNextPosition it }
|
||||
|
||||
if (endOfStream) return KtSourceFilePosition(-1, offset, if (withLineContents) currentLineContent else null)
|
||||
|
||||
currentLineContent = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun readNextLine() = buildString {
|
||||
while (true) {
|
||||
if (bufPos >= bufLength) {
|
||||
bufLength = reader.read(buffer)
|
||||
bufPos = 0
|
||||
if (bufLength < 0) {
|
||||
endOfStream = true
|
||||
break
|
||||
}
|
||||
} else {
|
||||
val c = buffer[bufPos++]
|
||||
charsRead++
|
||||
when {
|
||||
c == '\n' && skipNextLf -> {
|
||||
skipNextLf = false
|
||||
}
|
||||
c == '\n' || c == '\r' -> {
|
||||
currentLine++
|
||||
skipNextLf = c == '\r'
|
||||
break
|
||||
}
|
||||
else -> {
|
||||
append(c)
|
||||
skipNextLf = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
reader.close()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user