Extract the common part from bunched KtCodeFragment
This commit is contained in:
@@ -25,6 +25,7 @@ import com.intellij.psi.impl.source.tree.FileElement
|
|||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import com.intellij.testFramework.LightVirtualFile
|
import com.intellij.testFramework.LightVirtualFile
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -45,7 +46,7 @@ abstract class KtCodeFragment(
|
|||||||
text
|
text
|
||||||
), true
|
), true
|
||||||
), false
|
), false
|
||||||
), JavaCodeFragment {
|
), KtCodeFragmentBase {
|
||||||
|
|
||||||
private var viewProvider = super.getViewProvider() as SingleRootFileViewProvider
|
private var viewProvider = super.getViewProvider() as SingleRootFileViewProvider
|
||||||
private var imports = LinkedHashSet<String>()
|
private var imports = LinkedHashSet<String>()
|
||||||
@@ -167,10 +168,6 @@ abstract class KtCodeFragment(
|
|||||||
|
|
||||||
override fun getExceptionHandler() = exceptionHandler
|
override fun getExceptionHandler() = exceptionHandler
|
||||||
|
|
||||||
override fun importClass(aClass: PsiClass): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getContextContainingFile(): KtFile? {
|
fun getContextContainingFile(): KtFile? {
|
||||||
return getOriginalContext()?.containingKtFile
|
return getOriginalContext()?.containingKtFile
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,204 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2015 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.psi
|
|
||||||
|
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
|
||||||
import com.intellij.openapi.project.Project
|
|
||||||
import com.intellij.openapi.util.Key
|
|
||||||
import com.intellij.psi.*
|
|
||||||
import com.intellij.psi.impl.PsiManagerEx
|
|
||||||
import com.intellij.psi.impl.source.tree.FileElement
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
|
||||||
import com.intellij.psi.tree.IElementType
|
|
||||||
import com.intellij.testFramework.LightVirtualFile
|
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
abstract class KtCodeFragment(
|
|
||||||
private val _project: Project,
|
|
||||||
name: String,
|
|
||||||
text: CharSequence,
|
|
||||||
imports: String?, // Should be separated by JetCodeFragment.IMPORT_SEPARATOR
|
|
||||||
elementType: IElementType,
|
|
||||||
private val context: PsiElement?
|
|
||||||
) : KtFile(
|
|
||||||
(PsiManager.getInstance(_project) as PsiManagerEx).fileManager.createFileViewProvider(
|
|
||||||
LightVirtualFile(
|
|
||||||
name,
|
|
||||||
KotlinFileType.INSTANCE,
|
|
||||||
text
|
|
||||||
), true
|
|
||||||
), false
|
|
||||||
), JavaCodeFragment {
|
|
||||||
|
|
||||||
private var viewProvider = super.getViewProvider() as SingleRootFileViewProvider
|
|
||||||
private var imports = LinkedHashSet<String>()
|
|
||||||
|
|
||||||
private val fakeContextForJavaFile: PsiElement? by lazy {
|
|
||||||
this.getCopyableUserData(FAKE_CONTEXT_FOR_JAVA_FILE)?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
getViewProvider().forceCachedPsi(this)
|
|
||||||
init(TokenType.CODE_FRAGMENT, elementType)
|
|
||||||
if (context != null) {
|
|
||||||
initImports(imports)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override final fun init(elementType: IElementType, contentElementType: IElementType?) {
|
|
||||||
super.init(elementType, contentElementType)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var resolveScope: GlobalSearchScope? = null
|
|
||||||
private var thisType: PsiType? = null
|
|
||||||
private var superType: PsiType? = null
|
|
||||||
private var exceptionHandler: JavaCodeFragment.ExceptionHandler? = null
|
|
||||||
private var isPhysical = true
|
|
||||||
|
|
||||||
abstract fun getContentElement(): KtElement?
|
|
||||||
|
|
||||||
override fun forceResolveScope(scope: GlobalSearchScope?) {
|
|
||||||
resolveScope = scope
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getForcedResolveScope() = resolveScope
|
|
||||||
|
|
||||||
override fun isPhysical() = isPhysical
|
|
||||||
|
|
||||||
override fun isValid() = true
|
|
||||||
|
|
||||||
override fun getContext(): PsiElement? {
|
|
||||||
if (fakeContextForJavaFile != null) return fakeContextForJavaFile
|
|
||||||
if (context !is KtElement) {
|
|
||||||
val logInfoForContextElement = (context as? PsiFile)?.virtualFile?.path ?: context?.getElementTextWithContext()
|
|
||||||
LOG.warn("CodeFragment with non-kotlin context should have fakeContextForJavaFile set: \noriginalContext = $logInfoForContextElement")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return context
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getResolveScope() = context?.resolveScope ?: super.getResolveScope()
|
|
||||||
|
|
||||||
override fun clone(): KtCodeFragment {
|
|
||||||
val clone = cloneImpl(calcTreeElement().clone() as FileElement) as KtCodeFragment
|
|
||||||
clone.isPhysical = false
|
|
||||||
clone.myOriginalFile = this
|
|
||||||
clone.imports = imports
|
|
||||||
clone.viewProvider =
|
|
||||||
SingleRootFileViewProvider(PsiManager.getInstance(_project), LightVirtualFile(name, KotlinFileType.INSTANCE, text), false)
|
|
||||||
clone.viewProvider.forceCachedPsi(clone)
|
|
||||||
return clone
|
|
||||||
}
|
|
||||||
|
|
||||||
final override fun getViewProvider() = viewProvider
|
|
||||||
|
|
||||||
override fun getThisType() = thisType
|
|
||||||
|
|
||||||
override fun setThisType(psiType: PsiType?) {
|
|
||||||
thisType = psiType
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getSuperType() = superType
|
|
||||||
|
|
||||||
override fun setSuperType(superType: PsiType?) {
|
|
||||||
this.superType = superType
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun importsToString(): String {
|
|
||||||
return imports.joinToString(IMPORT_SEPARATOR)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun addImportsFromString(imports: String?) {
|
|
||||||
if (imports == null || imports.isEmpty()) return
|
|
||||||
|
|
||||||
imports.split(IMPORT_SEPARATOR).forEach {
|
|
||||||
addImport(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need this code to force re-highlighting, otherwise it does not work by some reason
|
|
||||||
val tempElement = KtPsiFactory(project).createColon()
|
|
||||||
add(tempElement).delete()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addImport(import: String) {
|
|
||||||
val contextFile = getContextContainingFile()
|
|
||||||
if (contextFile != null) {
|
|
||||||
if (contextFile.importDirectives.find { it.text == import } == null) {
|
|
||||||
imports.add(import)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun importsAsImportList(): KtImportList? {
|
|
||||||
if (!imports.isEmpty() && context != null) {
|
|
||||||
return KtPsiFactory(this).createAnalyzableFile("imports_for_codeFragment.kt", imports.joinToString("\n"), context).importList
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
override val importDirectives: List<KtImportDirective>
|
|
||||||
get() = importsAsImportList()?.imports ?: emptyList()
|
|
||||||
|
|
||||||
override fun setVisibilityChecker(checker: JavaCodeFragment.VisibilityChecker?) {}
|
|
||||||
|
|
||||||
override fun getVisibilityChecker() = JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE
|
|
||||||
|
|
||||||
override fun setExceptionHandler(checker: JavaCodeFragment.ExceptionHandler?) {
|
|
||||||
exceptionHandler = checker
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getExceptionHandler() = exceptionHandler
|
|
||||||
|
|
||||||
override fun importClass(aClass: PsiClass?): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getContextContainingFile(): KtFile? {
|
|
||||||
return getOriginalContext()?.containingKtFile
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOriginalContext(): KtElement? {
|
|
||||||
val contextElement = getContext() as? KtElement
|
|
||||||
val contextFile = contextElement?.containingKtFile
|
|
||||||
if (contextFile is KtCodeFragment) {
|
|
||||||
return contextFile.getOriginalContext()
|
|
||||||
}
|
|
||||||
return contextElement
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initImports(imports: String?) {
|
|
||||||
if (imports != null && !imports.isEmpty()) {
|
|
||||||
|
|
||||||
val importsWithPrefix = imports.split(IMPORT_SEPARATOR).map { it.takeIf { it.startsWith("import ") } ?: "import ${it.trim()}" }
|
|
||||||
importsWithPrefix.forEach {
|
|
||||||
addImport(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
val IMPORT_SEPARATOR: String = ","
|
|
||||||
val RUNTIME_TYPE_EVALUATOR: Key<Function1<KtExpression, KotlinType?>> = Key.create("RUNTIME_TYPE_EVALUATOR")
|
|
||||||
val FAKE_CONTEXT_FOR_JAVA_FILE: Key<Function0<KtElement>> = Key.create("FAKE_CONTEXT_FOR_JAVA_FILE")
|
|
||||||
|
|
||||||
private val LOG = Logger.getInstance(KtCodeFragment::class.java)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
|
import com.intellij.psi.JavaCodeFragment
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
|
||||||
|
interface KtCodeFragmentBase : JavaCodeFragment {
|
||||||
|
override fun importClass(aClass: PsiClass): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi
|
||||||
|
|
||||||
|
import com.intellij.psi.JavaCodeFragment
|
||||||
|
import com.intellij.psi.PsiClass
|
||||||
|
|
||||||
|
interface KtCodeFragmentBase : JavaCodeFragment {
|
||||||
|
override fun importClass(aClass: PsiClass?): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user