All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlin.psi2ir.PsiSourceManager.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
/*
 * Copyright 2010-2016 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jetbrains.kotlin.psi2ir

import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.SourceRangeInfo
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.psi.KtFile
import java.util.*

class PsiSourceManager : SourceManager {
    class PsiFileEntry(psiFile: PsiFile) : SourceManager.FileEntry {
        private val psiFileName = psiFile.virtualFile?.path ?: psiFile.name

        override val maxOffset: Int
        private val lineStartOffsets: IntArray

        init {
            val document = psiFile.viewProvider.document ?: throw AssertionError("No document for $psiFile")

            maxOffset = document.textLength

            lineStartOffsets = (0 .. document.lineCount - 1)
                    .map { document.getLineStartOffset(it) }
                    .toIntArray()
        }

        override fun getLineNumber(offset: Int): Int {
            if (offset < 0) return -1
            val index = lineStartOffsets.binarySearch(offset)
            return if (index >= 0) index else -index - 2
        }

        override fun getColumnNumber(offset: Int): Int {
            if (offset < 0) return -1
            val lineNumber = getLineNumber(offset)
            return offset - lineStartOffsets[lineNumber]
        }

        override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo =
                SourceRangeInfo(
                        filePath = getRecognizableName(),
                        startOffset = beginOffset,
                        startLineNumber = getLineNumber(beginOffset),
                        startColumnNumber = getColumnNumber(beginOffset),
                        endOffset = endOffset,
                        endLineNumber = getLineNumber(endOffset),
                        endColumnNumber = getColumnNumber(endOffset)
                )

        fun getRecognizableName(): String = psiFileName

        override val name: String get() = getRecognizableName()

        override fun toString(): String = getRecognizableName()
    }

    private val fileEntriesByKtFile = HashMap()
    private val fileEntriesByIrFile = HashMap()
    private val ktFileByFileEntry = HashMap()

    fun createFileEntry(ktFile: KtFile): PsiFileEntry {
        if (ktFile in fileEntriesByKtFile) error("PsiFileEntry is already created for $ktFile")
        val newEntry = PsiFileEntry(ktFile)
        fileEntriesByKtFile[ktFile] = newEntry
        ktFileByFileEntry[newEntry] = ktFile
        return newEntry
    }

    fun putFileEntry(irFile: IrFile, fileEntry: PsiFileEntry) {
        fileEntriesByIrFile[irFile] = fileEntry
    }

    fun getOrCreateFileEntry(ktFile: KtFile): PsiFileEntry =
            fileEntriesByKtFile.getOrElse(ktFile) { createFileEntry(ktFile) }

    fun getKtFile(fileEntry: PsiFileEntry): KtFile? =
            ktFileByFileEntry[fileEntry]

    fun getKtFile(irFile: IrFile): KtFile? =
            (irFile.fileEntry as? PsiFileEntry)?.let { ktFileByFileEntry[it] }

    override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry =
            fileEntriesByIrFile[irFile]!!
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy