mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-28 00:21:29 +00:00
Compare commits
27 Commits
rr/FIR/sem
...
fir-module
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b97f4091b | ||
|
|
9472481c44 | ||
|
|
d50cfa7457 | ||
|
|
ca8ef7dcff | ||
|
|
f4bbfde3ad | ||
|
|
8d3a41f650 | ||
|
|
1a4fc777dc | ||
|
|
7dfeb680f1 | ||
|
|
b4a21beeaa | ||
|
|
8fe8a554f0 | ||
|
|
81025fae5a | ||
|
|
865a0096ee | ||
|
|
2598e63a0e | ||
|
|
6ef870ce5a | ||
|
|
b5434163e1 | ||
|
|
deadd75003 | ||
|
|
558f77e1e1 | ||
|
|
da477eca36 | ||
|
|
e910ef1c28 | ||
|
|
5934c94040 | ||
|
|
b9bc8b0e34 | ||
|
|
4e11ab64c1 | ||
|
|
622fba5210 | ||
|
|
527ecc9251 | ||
|
|
2cf682cda0 | ||
|
|
f7aeda41b3 | ||
|
|
90ab774646 |
9
.idea/misc.xml
generated
9
.idea/misc.xml
generated
@@ -12,6 +12,7 @@
|
||||
<item index="2" class="java.lang.String" itemvalue="org.gradle.api.tasks.options.Option" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
@@ -88,6 +89,14 @@
|
||||
<option name="autoscroll" value="false" />
|
||||
<option name="showOnlyWarnings" value="false" />
|
||||
</component>
|
||||
<component name="idea.plugin.psiviewer.controller.project.PsiViewerProjectService">
|
||||
<option name="HIGHLIGHT" value="false" />
|
||||
<option name="FILTER_WHITESPACE" value="true" />
|
||||
<option name="SHOW_PROPERTIES" value="true" />
|
||||
<option name="SPLIT_DIVIDER_POSITION" value="300" />
|
||||
<option name="AUTOSCROLL_TO_SOURCE" value="true" />
|
||||
<option name="AUTOSCROLL_FROM_SOURCE" value="false" />
|
||||
</component>
|
||||
<component name="intellij-api-watcher-check-current-project">
|
||||
<option name="shouldCheckCurrentProject" value="true" />
|
||||
</component>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -85,7 +85,7 @@ class FirJavaModuleBasedSession(
|
||||
class FirLibrarySession private constructor(
|
||||
moduleInfo: ModuleInfo,
|
||||
sessionProvider: FirProjectSessionProvider,
|
||||
scope: GlobalSearchScope,
|
||||
val scope: GlobalSearchScope,
|
||||
packagePartProvider: PackagePartProvider,
|
||||
kotlinClassFinder: KotlinClassFinder,
|
||||
javaClassFinder: JavaClassFinder
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -67,6 +67,10 @@ class RawFirBuilder(
|
||||
return file.accept(Visitor(), Unit) as FirFile
|
||||
}
|
||||
|
||||
fun buildTypeReference(reference: KtTypeReference): FirTypeRef {
|
||||
return reference.accept(Visitor(), Unit) as FirTypeRef
|
||||
}
|
||||
|
||||
override fun PsiElement.toFirSourceElement(): FirPsiSourceElement<*> {
|
||||
return this.toFirPsiSourceElement()
|
||||
}
|
||||
@@ -249,13 +253,13 @@ class RawFirBuilder(
|
||||
val isSpread = getSpreadElement() != null
|
||||
return when {
|
||||
name != null -> buildNamedArgumentExpression {
|
||||
source = expression?.toFirSourceElement()
|
||||
source = (this@toFirExpression as? PsiElement)?.toFirSourceElement()
|
||||
this.expression = firExpression
|
||||
this.isSpread = isSpread
|
||||
this.name = name
|
||||
}
|
||||
isSpread -> buildSpreadArgumentExpression {
|
||||
source = expression?.toFirSourceElement()
|
||||
source = (this@toFirExpression as? PsiElement)?.toFirSourceElement()
|
||||
this.expression = firExpression
|
||||
}
|
||||
else -> firExpression
|
||||
|
||||
@@ -24,7 +24,7 @@ internal class FirBreakExpressionImpl(
|
||||
override val annotations: MutableList<FirAnnotationCall>,
|
||||
override val target: FirTarget<FirLoop>,
|
||||
) : FirBreakExpression() {
|
||||
override var typeRef: FirTypeRef = FirImplicitNothingTypeRef(source)
|
||||
override var typeRef: FirTypeRef = FirImplicitNothingTypeRef(null)
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
typeRef.accept(visitor, data)
|
||||
|
||||
@@ -24,7 +24,7 @@ internal class FirContinueExpressionImpl(
|
||||
override val annotations: MutableList<FirAnnotationCall>,
|
||||
override val target: FirTarget<FirLoop>,
|
||||
) : FirContinueExpression() {
|
||||
override var typeRef: FirTypeRef = FirImplicitNothingTypeRef(source)
|
||||
override var typeRef: FirTypeRef = FirImplicitNothingTypeRef(null)
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
typeRef.accept(visitor, data)
|
||||
|
||||
@@ -26,7 +26,7 @@ internal class FirReturnExpressionImpl(
|
||||
override val target: FirTarget<FirFunction<*>>,
|
||||
override var result: FirExpression,
|
||||
) : FirReturnExpression() {
|
||||
override var typeRef: FirTypeRef = FirImplicitNothingTypeRef(source)
|
||||
override var typeRef: FirTypeRef = FirImplicitNothingTypeRef(null)
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
typeRef.accept(visitor, data)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -243,7 +243,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
impl(resolvedReifiedParameterReference)
|
||||
|
||||
impl(returnExpression) {
|
||||
default("typeRef", "FirImplicitNothingTypeRef(source)")
|
||||
default("typeRef", "FirImplicitNothingTypeRef(null)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
|
||||
@@ -425,12 +425,12 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
}
|
||||
|
||||
impl(breakExpression) {
|
||||
default("typeRef", "FirImplicitNothingTypeRef(source)")
|
||||
default("typeRef", "FirImplicitNothingTypeRef(null)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
|
||||
impl(continueExpression) {
|
||||
default("typeRef", "FirImplicitNothingTypeRef(source)")
|
||||
default("typeRef", "FirImplicitNothingTypeRef(null)")
|
||||
useTypes(implicitNothingTypeRefType)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.resolve
|
||||
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object ArrayFqNames {
|
||||
val PRIMITIVE_TYPE_TO_ARRAY: Map<PrimitiveType, Name> = hashMapOf(
|
||||
PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"),
|
||||
PrimitiveType.CHAR to Name.identifier("charArrayOf"),
|
||||
PrimitiveType.INT to Name.identifier("intArrayOf"),
|
||||
PrimitiveType.BYTE to Name.identifier("byteArrayOf"),
|
||||
PrimitiveType.SHORT to Name.identifier("shortArrayOf"),
|
||||
PrimitiveType.FLOAT to Name.identifier("floatArrayOf"),
|
||||
PrimitiveType.LONG to Name.identifier("longArrayOf"),
|
||||
PrimitiveType.DOUBLE to Name.identifier("doubleArrayOf")
|
||||
)
|
||||
|
||||
val ARRAY_OF_FUNCTION = Name.identifier("arrayOf")
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.resolve
|
||||
@@ -44,21 +33,6 @@ class CollectionLiteralResolver(
|
||||
val callResolver: CallResolver,
|
||||
val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
companion object {
|
||||
val PRIMITIVE_TYPE_TO_ARRAY: Map<PrimitiveType, Name> = hashMapOf(
|
||||
PrimitiveType.BOOLEAN to Name.identifier("booleanArrayOf"),
|
||||
PrimitiveType.CHAR to Name.identifier("charArrayOf"),
|
||||
PrimitiveType.INT to Name.identifier("intArrayOf"),
|
||||
PrimitiveType.BYTE to Name.identifier("byteArrayOf"),
|
||||
PrimitiveType.SHORT to Name.identifier("shortArrayOf"),
|
||||
PrimitiveType.FLOAT to Name.identifier("floatArrayOf"),
|
||||
PrimitiveType.LONG to Name.identifier("longArrayOf"),
|
||||
PrimitiveType.DOUBLE to Name.identifier("doubleArrayOf")
|
||||
)
|
||||
|
||||
val ARRAY_OF_FUNCTION = Name.identifier("arrayOf")
|
||||
}
|
||||
|
||||
fun resolveCollectionLiteral(
|
||||
collectionLiteralExpression: KtCollectionLiteralExpression,
|
||||
context: ExpressionTypingContext
|
||||
@@ -120,11 +94,11 @@ class CollectionLiteralResolver(
|
||||
|
||||
private fun getArrayFunctionCallName(expectedType: KotlinType): Name {
|
||||
if (NO_EXPECTED_TYPE === expectedType || !KotlinBuiltIns.isPrimitiveArray(expectedType)) {
|
||||
return ARRAY_OF_FUNCTION
|
||||
return ArrayFqNames.ARRAY_OF_FUNCTION
|
||||
}
|
||||
|
||||
val descriptor = expectedType.constructor.declarationDescriptor ?: return ARRAY_OF_FUNCTION
|
||||
val descriptor = expectedType.constructor.declarationDescriptor ?: return ArrayFqNames.ARRAY_OF_FUNCTION
|
||||
|
||||
return PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ARRAY_OF_FUNCTION
|
||||
return ArrayFqNames.PRIMITIVE_TYPE_TO_ARRAY[KotlinBuiltIns.getPrimitiveArrayType(descriptor)] ?: ArrayFqNames.ARRAY_OF_FUNCTION
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.utils.addToStdlib
|
||||
@@ -50,6 +39,17 @@ inline fun <reified T> Array<*>.firstIsInstance(): T {
|
||||
throw NoSuchElementException("No element of given type found")
|
||||
}
|
||||
|
||||
inline fun <reified T> Iterable<*>.filterIsInstanceWithChecker(additionalChecker: (T) -> Boolean): List<T> {
|
||||
val result = arrayListOf<T>()
|
||||
for (element in this) {
|
||||
if (element is T && additionalChecker(element)) {
|
||||
result += element
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
inline fun <reified T : Any> Iterable<*>.lastIsInstanceOrNull(): T? {
|
||||
when (this) {
|
||||
is List<*> -> {
|
||||
|
||||
@@ -38,6 +38,7 @@ dependencies {
|
||||
testCompile(projectTests(":compiler:cli"))
|
||||
testCompile(projectTests(":idea:idea-maven"))
|
||||
testCompile(projectTests(":idea:idea-fir"))
|
||||
testCompile(projectTests(":idea:idea-frontend-fir"))
|
||||
testCompile(projectTests(":j2k"))
|
||||
testCompile(projectTests(":nj2k"))
|
||||
if (Ide.IJ()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -84,6 +84,7 @@ import org.jetbrains.kotlin.idea.editor.quickDoc.AbstractQuickDocProviderTest
|
||||
import org.jetbrains.kotlin.idea.filters.AbstractKotlinExceptionFilterTest
|
||||
import org.jetbrains.kotlin.idea.fir.AbstractFirLazyResolveTest
|
||||
import org.jetbrains.kotlin.idea.fir.AbstractFirMultiModuleResolveTest
|
||||
import org.jetbrains.kotlin.idea.fir.AbstractKtDeclarationAndFirDeclarationEqualityChecker
|
||||
import org.jetbrains.kotlin.idea.folding.AbstractKotlinFoldingTest
|
||||
import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyTest
|
||||
import org.jetbrains.kotlin.idea.hierarchy.AbstractHierarchyWithLibTest
|
||||
@@ -904,11 +905,21 @@ fun main() {
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/idea-frontend-fir/tests", "idea/idea-frontend-fir/testData") {
|
||||
testClass<AbstractKtDeclarationAndFirDeclarationEqualityChecker> {
|
||||
model("ktDeclarationAndFirDeclarationEqualityChecker")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("idea/idea-fir/tests", "idea/testData") {
|
||||
testClass<AbstractFirMultiModuleResolveTest> {
|
||||
model("fir/multiModule", recursive = false, extension = null)
|
||||
}
|
||||
|
||||
testClass<AbstractFirHighlightingTest> {
|
||||
model("highlighter")
|
||||
}
|
||||
|
||||
testClass<AbstractFirLazyResolveTest> {
|
||||
model("fir/lazyResolve", extension = "test", singleClass = true, filenameStartsLowerCase = true)
|
||||
}
|
||||
@@ -922,7 +933,6 @@ fun main() {
|
||||
model("checker/regression")
|
||||
model("checker/recovery")
|
||||
model("checker/rendering")
|
||||
model("checker/duplicateJvmSignature")
|
||||
model("checker/infos")
|
||||
model("checker/diagnosticsMessage")
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ plugins {
|
||||
}
|
||||
|
||||
val kotlinVersion: String by rootProject.extra
|
||||
val isFirPlugin: Boolean
|
||||
get() = rootProject.findProperty("idea.fir.plugin") == "true"
|
||||
|
||||
|
||||
repositories {
|
||||
maven("https://jetbrains.bintray.com/markdown")
|
||||
@@ -25,6 +28,11 @@ sourceSets {
|
||||
"idea-repl/resources",
|
||||
"resources-en"
|
||||
)
|
||||
if (isFirPlugin) {
|
||||
resources.srcDir("resources-fir")
|
||||
} else {
|
||||
resources.srcDir("resources-descriptors")
|
||||
}
|
||||
}
|
||||
"test" {
|
||||
projectDefault()
|
||||
@@ -71,6 +79,7 @@ dependencies {
|
||||
compile(project(":compiler:fir:java"))
|
||||
compile(project(":compiler:fir:jvm"))
|
||||
compile(project(":idea:idea-core"))
|
||||
compile(project(":idea:idea-frontend-independent"))
|
||||
compile(project(":idea:ide-common"))
|
||||
compile(project(":idea:idea-jps-common"))
|
||||
compile(project(":idea:kotlin-gradle-tooling"))
|
||||
|
||||
@@ -10,14 +10,11 @@ import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.lang.annotation.Annotation
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import com.intellij.xml.util.XmlStringUtil
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.idea.inspections.KotlinUniversalQuickFix
|
||||
|
||||
class AnnotationPresentationInfo(
|
||||
@@ -52,55 +49,14 @@ class AnnotationPresentationInfo(
|
||||
}
|
||||
}
|
||||
|
||||
private fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation {
|
||||
val defaultMessage = nonDefaultMessage ?: getDefaultMessage(diagnostic)
|
||||
|
||||
val annotation = when (diagnostic.severity) {
|
||||
Severity.ERROR -> holder.createErrorAnnotation(range, defaultMessage)
|
||||
Severity.WARNING -> {
|
||||
if (highlightType == ProblemHighlightType.WEAK_WARNING) {
|
||||
holder.createWeakWarningAnnotation(range, defaultMessage)
|
||||
} else {
|
||||
holder.createWarningAnnotation(range, defaultMessage)
|
||||
}
|
||||
}
|
||||
Severity.INFO -> holder.createInfoAnnotation(range, defaultMessage)
|
||||
}
|
||||
|
||||
annotation.tooltip = getMessage(diagnostic)
|
||||
|
||||
if (highlightType != null) {
|
||||
annotation.highlightType = highlightType
|
||||
}
|
||||
|
||||
if (textAttributes != null) {
|
||||
annotation.textAttributes = textAttributes
|
||||
}
|
||||
|
||||
return annotation
|
||||
}
|
||||
|
||||
private fun getMessage(diagnostic: Diagnostic): String {
|
||||
var message = IdeErrorMessages.render(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
val factoryName = diagnostic.factory.name
|
||||
message = if (message.startsWith("<html>")) {
|
||||
"<html>[$factoryName] ${message.substring("<html>".length)}"
|
||||
} else {
|
||||
"[$factoryName] $message"
|
||||
}
|
||||
}
|
||||
if (!message.startsWith("<html>")) {
|
||||
message = "<html><body>${XmlStringUtil.escapeString(message)}</body></html>"
|
||||
}
|
||||
return message
|
||||
}
|
||||
|
||||
private fun getDefaultMessage(diagnostic: Diagnostic): String {
|
||||
val message = DefaultErrorMessages.render(diagnostic)
|
||||
if (ApplicationManager.getApplication().isInternal || ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return "[${diagnostic.factory.name}] $message"
|
||||
}
|
||||
return message
|
||||
}
|
||||
private fun create(diagnostic: Diagnostic, range: TextRange, holder: AnnotationHolder): Annotation =
|
||||
Diagnostic2Annotation.createAnnotation(
|
||||
diagnostic,
|
||||
range,
|
||||
holder,
|
||||
nonDefaultMessage,
|
||||
textAttributes,
|
||||
highlightType,
|
||||
IdeErrorMessages::render
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -28,21 +28,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||
internal class FunctionsHighlightingVisitor(holder: AnnotationHolder, bindingContext: BindingContext) :
|
||||
AfterAnalysisHighlightingVisitor(holder, bindingContext) {
|
||||
|
||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||
function.nameIdentifier?.let { highlightName(it, FUNCTION_DECLARATION) }
|
||||
|
||||
super.visitNamedFunction(function)
|
||||
}
|
||||
|
||||
override fun visitSuperTypeCallEntry(call: KtSuperTypeCallEntry) {
|
||||
val calleeExpression = call.calleeExpression
|
||||
val typeElement = calleeExpression.typeReference?.typeElement
|
||||
if (typeElement is KtUserType) {
|
||||
typeElement.referenceExpression?.let { highlightName(it, CONSTRUCTOR_CALL) }
|
||||
}
|
||||
super.visitSuperTypeCallEntry(call)
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
||||
if (expression.operationReference.getIdentifier() != null) {
|
||||
val resolvedCall = expression.getResolvedCall(bindingContext)
|
||||
|
||||
@@ -1,26 +1,13 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightRangeExtension
|
||||
import com.intellij.codeInsight.intention.IntentionAction
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.lang.annotation.Annotator
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors
|
||||
@@ -28,7 +15,6 @@ import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.MultiRangeReference
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.util.containers.MultiMap
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.config.KotlinFacetSettingsProvider
|
||||
@@ -38,35 +24,23 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.Severity
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
|
||||
import org.jetbrains.kotlin.idea.fir.FirResolution
|
||||
import org.jetbrains.kotlin.idea.fir.firResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFirWithDiagnostics
|
||||
import org.jetbrains.kotlin.idea.quickfix.QuickFixes
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.util.module
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.lang.reflect.*
|
||||
import java.util.*
|
||||
|
||||
open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
open class KotlinPsiChecker : AbstractKotlinPsiChecker() {
|
||||
override fun shouldHighlight(file: KtFile): Boolean = KotlinHighlightingUtil.shouldHighlight(file)
|
||||
|
||||
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
||||
val file = element.containingFile as? KtFile ?: return
|
||||
|
||||
if (!KotlinHighlightingUtil.shouldHighlight(file)) return
|
||||
|
||||
if (FirResolution.enabled) {
|
||||
annotateElementUsingFrontendIR(element, file, holder)
|
||||
} else {
|
||||
annotateElement(element, file, holder)
|
||||
}
|
||||
}
|
||||
|
||||
private fun annotateElement(
|
||||
override fun annotateElement(
|
||||
element: PsiElement,
|
||||
containingFile: KtFile,
|
||||
holder: AnnotationHolder
|
||||
@@ -83,29 +57,6 @@ open class KotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
annotateElement(element, holder, bindingContext.diagnostics)
|
||||
}
|
||||
|
||||
private fun annotateElementUsingFrontendIR(
|
||||
element: PsiElement,
|
||||
containingFile: KtFile,
|
||||
holder: AnnotationHolder
|
||||
) {
|
||||
if (element !is KtElement) return
|
||||
val state = containingFile.firResolveState()
|
||||
containingFile.getOrBuildFirWithDiagnostics(state)
|
||||
|
||||
val diagnostics = state.getDiagnostics(element)
|
||||
if (diagnostics.isEmpty()) return
|
||||
|
||||
if (KotlinHighlightingUtil.shouldHighlightErrors(element)) {
|
||||
ElementAnnotator(element, holder) { param ->
|
||||
shouldSuppressUnusedParameter(param)
|
||||
}.registerDiagnosticsAnnotations(diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isForceHighlightParents(file: PsiFile): Boolean {
|
||||
return file is KtFile
|
||||
}
|
||||
|
||||
protected open fun shouldSuppressUnusedParameter(parameter: KtParameter): Boolean = false
|
||||
|
||||
fun annotateElement(element: PsiElement, holder: AnnotationHolder, diagnostics: Diagnostics) {
|
||||
|
||||
@@ -1,25 +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.idea.highlighter
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
|
||||
object NameHighlighter {
|
||||
var namesHighlightingEnabled = true
|
||||
@TestOnly set
|
||||
}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter
|
||||
@@ -92,11 +81,6 @@ internal class TypeKindHighlightingVisitor(holder: AnnotationHolder, bindingCont
|
||||
return TextRange(atSymbol.textRange.startOffset, expression.textRange.endOffset)
|
||||
}
|
||||
|
||||
override fun visitTypeParameter(parameter: KtTypeParameter) {
|
||||
parameter.nameIdentifier?.let { highlightName(it, TYPE_PARAMETER) }
|
||||
super.visitTypeParameter(parameter)
|
||||
}
|
||||
|
||||
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||
val identifier = classOrObject.nameIdentifier
|
||||
val classDescriptor = bindingContext.get(BindingContext.CLASS, classOrObject)
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.kdoc
|
||||
@@ -20,6 +9,8 @@ import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.references.KDocReference
|
||||
import org.jetbrains.kotlin.idea.references.KtDescriptorsBasedReference
|
||||
import org.jetbrains.kotlin.idea.references.KtMultiReference
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
||||
@@ -28,7 +19,10 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
|
||||
class KDocReference(element: KDocName) : KtMultiReference<KDocName>(element) {
|
||||
class KDocReferenceDescriptorsImpl(element: KDocName) : KDocReference(element), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val declaration = element.getContainingDoc().getOwner() ?: return arrayListOf()
|
||||
val resolutionFacade = element.getResolutionFacade()
|
||||
@@ -45,20 +39,10 @@ class KDocReference(element: KDocName) : KtMultiReference<KDocName>(element) {
|
||||
)
|
||||
}
|
||||
|
||||
override fun getRangeInElement(): TextRange = element.getNameTextRange()
|
||||
|
||||
override fun canRename(): Boolean = true
|
||||
|
||||
override fun resolve(): PsiElement? = multiResolve(false).firstOrNull()?.element
|
||||
|
||||
override fun handleElementRename(newElementName: String): PsiElement? {
|
||||
val textRange = element.getNameTextRange()
|
||||
val newText = textRange.replace(element.text, newElementName)
|
||||
val newLink = KDocElementFactory(element.project).createNameFromText(newText)
|
||||
return element.replace(newLink)
|
||||
}
|
||||
|
||||
override fun getCanonicalText(): String = element.getNameText()
|
||||
|
||||
override val resolvesByNames: Collection<Name> get() = listOf(Name.identifier(element.getNameText()))
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -66,14 +66,10 @@ class ReferenceImpl(private val argument: KtValueArgument) : PsiReference {
|
||||
override fun isSoft() = false
|
||||
}
|
||||
|
||||
internal class KotlinDefaultAnnotationMethodImplicitReferenceContributor : KotlinReferenceProviderContributor {
|
||||
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
|
||||
registrar.registerProvider<KtValueArgument> {
|
||||
if (it.isNamed()) return@registerProvider null
|
||||
val annotationEntry = it.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@registerProvider null
|
||||
if (annotationEntry.valueArguments.size != 1) return@registerProvider null
|
||||
internal val KotlinDefaultAnnotationMethodImplicitReferenceProvider = provider@{ element: KtValueArgument ->
|
||||
if (element.isNamed()) return@provider null
|
||||
val annotationEntry = element.getParentOfTypeAndBranch<KtAnnotationEntry> { valueArgumentList } ?: return@provider null
|
||||
if (annotationEntry.valueArguments.size != 1) return@provider null
|
||||
|
||||
ReferenceImpl(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
ReferenceImpl(element)
|
||||
}
|
||||
@@ -1,22 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import org.jetbrains.kotlin.idea.kdoc.KDocReference
|
||||
import org.jetbrains.kotlin.idea.kdoc.KDocReferenceDescriptorsImpl
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtImportDirective
|
||||
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
|
||||
@@ -24,10 +13,10 @@ import org.jetbrains.kotlin.psi.KtPackageDirective
|
||||
import org.jetbrains.kotlin.psi.KtUserType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
|
||||
internal class KotlinReferenceContributor : KotlinReferenceProviderContributor {
|
||||
class KotlinReferenceContributor : KotlinReferenceProviderContributor {
|
||||
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
|
||||
with(registrar) {
|
||||
registerProvider(factory = ::KtSimpleNameReference)
|
||||
registerProvider(factory = ::KtSimpleNameReferenceDescriptorsImpl)
|
||||
|
||||
registerMultiProvider<KtNameReferenceExpression> { nameReferenceExpression ->
|
||||
if (nameReferenceExpression.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMultiProvider emptyArray()
|
||||
@@ -37,32 +26,34 @@ internal class KotlinReferenceContributor : KotlinReferenceProviderContributor {
|
||||
|
||||
when (nameReferenceExpression.readWriteAccess(useResolveForReadWrite = false)) {
|
||||
ReferenceAccess.READ ->
|
||||
arrayOf(SyntheticPropertyAccessorReference.Getter(nameReferenceExpression))
|
||||
arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true))
|
||||
ReferenceAccess.WRITE ->
|
||||
arrayOf(SyntheticPropertyAccessorReference.Setter(nameReferenceExpression))
|
||||
arrayOf(SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = false))
|
||||
ReferenceAccess.READ_WRITE ->
|
||||
arrayOf(
|
||||
SyntheticPropertyAccessorReference.Getter(nameReferenceExpression),
|
||||
SyntheticPropertyAccessorReference.Setter(nameReferenceExpression)
|
||||
SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = true),
|
||||
SyntheticPropertyAccessorReferenceDescriptorImpl(nameReferenceExpression, getter = false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
registerProvider(factory = ::KtConstructorDelegationReference)
|
||||
registerProvider(factory = ::KtConstructorDelegationReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(factory = ::KtInvokeFunctionReference)
|
||||
registerProvider(factory = ::KtInvokeFunctionReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(factory = ::KtArrayAccessReference)
|
||||
registerProvider(factory = ::KtArrayAccessReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(factory = ::KtCollectionLiteralReference)
|
||||
registerProvider(factory = ::KtCollectionLiteralReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(factory = ::KtForLoopInReference)
|
||||
registerProvider(factory = ::KtForLoopInReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(factory = ::KtPropertyDelegationMethodsReference)
|
||||
registerProvider(factory = ::KtPropertyDelegationMethodsReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(factory = ::KtDestructuringDeclarationReference)
|
||||
registerProvider(factory = ::KtDestructuringDeclarationReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(factory = ::KDocReference)
|
||||
registerProvider(factory = ::KDocReferenceDescriptorsImpl)
|
||||
|
||||
registerProvider(KotlinDefaultAnnotationMethodImplicitReferenceProvider)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.MultiRangeReference
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.canMoveLambdaOutsideParentheses
|
||||
import org.jetbrains.kotlin.idea.core.moveFunctionLiteralOutsideParentheses
|
||||
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_GET
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.INDEXED_LVALUE_SET
|
||||
|
||||
internal class KtArrayAccessReferenceDescriptorsImpl(
|
||||
expression: KtArrayAccessExpression
|
||||
) : KtArrayAccessReference(expression), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
override fun moveFunctionLiteralOutsideParentheses(callExpression: KtCallExpression) {
|
||||
callExpression.moveFunctionLiteralOutsideParentheses()
|
||||
}
|
||||
|
||||
override fun canMoveLambdaOutsideParentheses(callExpression: KtCallExpression): Boolean =
|
||||
callExpression.canMoveLambdaOutsideParentheses()
|
||||
|
||||
override fun doRenameImplicitConventionalCall(newName: String?): KtExpression =
|
||||
renameImplicitConventionalCall(newName)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val getFunctionDescriptor = context[INDEXED_LVALUE_GET, expression]?.candidateDescriptor
|
||||
val setFunctionDescriptor = context[INDEXED_LVALUE_SET, expression]?.candidateDescriptor
|
||||
return listOfNotNull(getFunctionDescriptor, setFunctionDescriptor)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class KtCollectionLiteralReferenceDescriptorsImpl(
|
||||
expression: KtCollectionLiteralExpression
|
||||
) : KtCollectionLiteralReference(expression), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val resolvedCall = context[BindingContext.COLLECTION_LITERAL_CALL, element]
|
||||
return listOfNotNull(resolvedCall?.resultingDescriptor)
|
||||
}
|
||||
}
|
||||
@@ -1,51 +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.idea.references;
|
||||
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class KtConstructorDelegationReference extends KtSimpleReference<KtConstructorDelegationReferenceExpression> {
|
||||
public KtConstructorDelegationReference(KtConstructorDelegationReferenceExpression expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextRange getRangeInElement() {
|
||||
return new TextRange(0, getElement().getTextLength());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Name> getResolvesByNames() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement handleElementRename(@Nullable String newElementName) {
|
||||
// Class rename never affects this reference, so there is no need to fail with exception
|
||||
return getExpression();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.psi.KtConstructorDelegationReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
||||
|
||||
class KtConstructorDelegationReferenceDescriptorsImpl(
|
||||
expression: KtConstructorDelegationReferenceExpression
|
||||
) : KtConstructorDelegationReference(expression), KtDescriptorsBasedReference {
|
||||
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -16,8 +16,12 @@ import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEntry) :
|
||||
AbstractKtReference<KtDestructuringDeclarationEntry>(element) {
|
||||
class KtDestructuringDeclarationReferenceDescriptorsImpl(
|
||||
element: KtDestructuringDeclarationEntry
|
||||
) : KtDestructuringDeclarationReference(element), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
return listOfNotNull(context[BindingContext.COMPONENT_RESOLVED_CALL, element]?.candidateDescriptor)
|
||||
}
|
||||
@@ -30,16 +34,4 @@ class KtDestructuringDeclarationReference(element: KtDestructuringDeclarationEnt
|
||||
it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleElementRename(newElementName: String): PsiElement? {
|
||||
if (canRename()) return expression
|
||||
throw IncorrectOperationException()
|
||||
}
|
||||
|
||||
override val resolvesByNames: Collection<Name>
|
||||
get() {
|
||||
val destructuringParent = element.parent as? KtDestructuringDeclaration ?: return emptyList()
|
||||
val componentIndex = destructuringParent.entries.indexOf(element) + 1
|
||||
return listOf(Name.identifier("component$componentIndex"))
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class KtForLoopInReference(element: KtForExpression) : KtMultiReference<KtForExpression>(element) {
|
||||
|
||||
override fun getRangeInElement(): TextRange {
|
||||
val inKeyword = expression.inKeyword ?: return TextRange.EMPTY_RANGE
|
||||
|
||||
val offset = inKeyword.startOffsetInParent
|
||||
return TextRange(offset, offset + inKeyword.textLength)
|
||||
}
|
||||
class KtForLoopInReferenceDescriptorsImpl(
|
||||
element: KtForExpression
|
||||
) : KtForLoopInReference(element), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val loopRange = expression.loopRange ?: return emptyList()
|
||||
return LOOP_RANGE_KEYS.mapNotNull { key -> context.get(key, loopRange)?.candidateDescriptor }
|
||||
}
|
||||
|
||||
override val resolvesByNames: Collection<Name>
|
||||
get() = NAMES
|
||||
|
||||
companion object {
|
||||
private val LOOP_RANGE_KEYS = arrayOf(
|
||||
BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL,
|
||||
BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL,
|
||||
BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL
|
||||
)
|
||||
|
||||
private val NAMES = listOf(
|
||||
OperatorNameConventions.ITERATOR,
|
||||
OperatorNameConventions.NEXT,
|
||||
OperatorNameConventions.HAS_NEXT
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.psi.Call
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
|
||||
class KtInvokeFunctionReferenceDescriptorsImpl(expression: KtCallExpression) : KtInvokeFunctionReference(expression), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val call = element.getCall(context)
|
||||
val resolvedCall = call.getResolvedCall(context)
|
||||
return when {
|
||||
resolvedCall is VariableAsFunctionResolvedCall ->
|
||||
setOf<DeclarationDescriptor>((resolvedCall as VariableAsFunctionResolvedCall).functionCall.candidateDescriptor)
|
||||
call != null && resolvedCall != null && call.callType == Call.CallType.INVOKE ->
|
||||
setOf<DeclarationDescriptor>(resolvedCall.candidateDescriptor)
|
||||
else ->
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun doRenameImplicitConventionalCall(newName: String?): KtExpression =
|
||||
renameImplicitConventionalCall(newName)
|
||||
}
|
||||
@@ -1,56 +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.idea.references
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||
import org.jetbrains.kotlin.descriptors.accessors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class KtPropertyDelegationMethodsReference(element: KtPropertyDelegate) : KtMultiReference<KtPropertyDelegate>(element) {
|
||||
|
||||
override fun getRangeInElement(): TextRange {
|
||||
val byKeywordNode = expression.byKeywordNode
|
||||
val offset = byKeywordNode.psi!!.startOffsetInParent
|
||||
return TextRange(offset, offset + byKeywordNode.textLength)
|
||||
}
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val property = expression.getStrictParentOfType<KtProperty>() ?: return emptyList()
|
||||
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptorWithAccessors
|
||||
?: return emptyList()
|
||||
return (descriptor.accessors.mapNotNull { accessor ->
|
||||
context.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor)?.candidateDescriptor
|
||||
} + listOfNotNull(context.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor)?.candidateDescriptor))
|
||||
}
|
||||
|
||||
override val resolvesByNames: Collection<Name> get() = NAMES
|
||||
|
||||
companion object {
|
||||
private val NAMES = listOf(
|
||||
OperatorNameConventions.GET_VALUE,
|
||||
OperatorNameConventions.SET_VALUE,
|
||||
OperatorNameConventions.PROVIDE_DELEGATE
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
|
||||
import org.jetbrains.kotlin.descriptors.accessors
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class KtPropertyDelegationMethodsReferenceDescriptorsImpl(
|
||||
element: KtPropertyDelegate
|
||||
) : KtPropertyDelegationMethodsReference(element), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val property = expression.getStrictParentOfType<KtProperty>() ?: return emptyList()
|
||||
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, property] as? VariableDescriptorWithAccessors
|
||||
?: return emptyList()
|
||||
return descriptor.accessors.mapNotNull { accessor ->
|
||||
context.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, accessor)?.candidateDescriptor
|
||||
} + listOfNotNull(context.get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor)?.candidateDescriptor)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
@@ -35,9 +24,6 @@ import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.fir.FirResolution
|
||||
import org.jetbrains.kotlin.idea.fir.firResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFir
|
||||
import org.jetbrains.kotlin.idea.util.application.runWithCancellationCheck
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -51,251 +37,79 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import java.util.*
|
||||
|
||||
interface KtReference : PsiPolyVariantReference {
|
||||
fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor>
|
||||
interface KtDescriptorsBasedReference : KtReference {
|
||||
override val resolver get() = KotlinDescriptorsBasedReferenceResolver
|
||||
|
||||
override fun getElement(): KtElement
|
||||
|
||||
val resolvesByNames: Collection<Name>
|
||||
}
|
||||
|
||||
abstract class AbstractKtReference<T : KtElement>(element: T) : PsiPolyVariantReferenceBase<T>(element), KtReference {
|
||||
val expression: T
|
||||
get() = element
|
||||
|
||||
override fun multiResolve(incompleteCode: Boolean): Array<ResolveResult> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val kotlinResolver = KOTLIN_RESOLVER as ResolveCache.PolyVariantResolver<AbstractKtReference<T>>
|
||||
return ResolveCache.getInstance(expression.project).resolveWithCaching(this, kotlinResolver, false, incompleteCode)
|
||||
fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
|
||||
return getTargetDescriptors(bindingContext)
|
||||
}
|
||||
|
||||
fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor>
|
||||
|
||||
override fun isReferenceTo(element: PsiElement): Boolean {
|
||||
return matchesTarget(element)
|
||||
}
|
||||
|
||||
override fun getCanonicalText(): String = "<TBD>"
|
||||
|
||||
open fun canRename(): Boolean = false
|
||||
override fun handleElementRename(newElementName: String): PsiElement? = throw IncorrectOperationException()
|
||||
|
||||
override fun bindToElement(element: PsiElement): PsiElement = throw IncorrectOperationException()
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun getVariants(): Array<Any> = PsiReference.EMPTY_ARRAY as Array<Any>
|
||||
|
||||
override fun isSoft(): Boolean = false
|
||||
|
||||
override fun resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
|
||||
return getTargetDescriptors(bindingContext)
|
||||
}
|
||||
|
||||
protected abstract fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor>
|
||||
|
||||
override fun toString() = this::class.java.simpleName + ": " + expression.text
|
||||
|
||||
companion object {
|
||||
private object FirReferenceResolveHelper {
|
||||
fun FirResolvedTypeRef.toTargetPsi(session: FirSession): PsiElement? {
|
||||
val type = type as? ConeLookupTagBasedType ?: return null
|
||||
return (type.lookupTag.toSymbol(session) as? AbstractFirBasedSymbol<*>)?.fir?.psi
|
||||
}
|
||||
|
||||
fun ClassId.toTargetPsi(session: FirSession, calleeReference: FirReference? = null): PsiElement? {
|
||||
val classLikeDeclaration = ConeClassLikeLookupTagImpl(this).toSymbol(session)?.fir
|
||||
if (classLikeDeclaration is FirRegularClass) {
|
||||
if (calleeReference is FirResolvedNamedReference) {
|
||||
val callee = calleeReference.resolvedSymbol.fir as? FirCallableMemberDeclaration
|
||||
// TODO: check callee owner directly?
|
||||
if (callee !is FirConstructor && callee?.isStatic != true) {
|
||||
classLikeDeclaration.companionObject?.let { return it.psi }
|
||||
}
|
||||
}
|
||||
}
|
||||
return classLikeDeclaration?.psi
|
||||
}
|
||||
|
||||
fun FirReference.toTargetPsi(session: FirSession): PsiElement? {
|
||||
return when (this) {
|
||||
is FirResolvedNamedReference -> {
|
||||
resolvedSymbol.fir.psi
|
||||
}
|
||||
is FirResolvedCallableReference -> {
|
||||
resolvedSymbol.fir.psi
|
||||
}
|
||||
is FirThisReference -> {
|
||||
boundSymbol?.fir?.psi
|
||||
}
|
||||
is FirSuperReference -> {
|
||||
(superTypeRef as? FirResolvedTypeRef)?.toTargetPsi(session)
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun resolveToPsiElements(ref: AbstractKtReference<KtElement>): Collection<PsiElement> {
|
||||
val expression = ref.expression
|
||||
val state = expression.firResolveState()
|
||||
val session = state.getSession(expression)
|
||||
when (val fir = expression.getOrBuildFir(state)) {
|
||||
is FirResolvable -> {
|
||||
return listOfNotNull(fir.calleeReference.toTargetPsi(session))
|
||||
}
|
||||
is FirResolvedTypeRef -> {
|
||||
return listOfNotNull(fir.toTargetPsi(session))
|
||||
}
|
||||
is FirResolvedQualifier -> {
|
||||
val classId = fir.classId ?: return emptyList()
|
||||
// Distinguish A.foo() from A(.Companion).foo()
|
||||
// Make expression.parent as? KtDotQualifiedExpression local function
|
||||
var parent = expression.parent as? KtDotQualifiedExpression
|
||||
while (parent != null) {
|
||||
val selectorExpression = parent.selectorExpression ?: break
|
||||
if (selectorExpression === expression) {
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
continue
|
||||
}
|
||||
val parentFir = selectorExpression.getOrBuildFir(state)
|
||||
if (parentFir is FirQualifiedAccess) {
|
||||
return listOfNotNull(classId.toTargetPsi(session, parentFir.calleeReference))
|
||||
}
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
}
|
||||
return listOfNotNull(classId.toTargetPsi(session))
|
||||
}
|
||||
is FirAnnotationCall -> {
|
||||
val type = fir.typeRef as? FirResolvedTypeRef ?: return emptyList()
|
||||
return listOfNotNull(type.toTargetPsi(session))
|
||||
}
|
||||
is FirResolvedImport -> {
|
||||
var parent = expression.parent
|
||||
while (parent is KtDotQualifiedExpression) {
|
||||
if (parent.selectorExpression !== expression) {
|
||||
// Special: package reference in the middle of import directive
|
||||
// import a.<caret>b.c.SomeClass
|
||||
// TODO: return reference to PsiPackage
|
||||
return listOf(expression)
|
||||
}
|
||||
parent = parent.parent
|
||||
}
|
||||
val classId = fir.resolvedClassId
|
||||
if (classId != null) {
|
||||
return listOfNotNull(classId.toTargetPsi(session))
|
||||
}
|
||||
val name = fir.importedName ?: return emptyList()
|
||||
val symbolProvider = session.firSymbolProvider
|
||||
return symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name).mapNotNull { it.fir.psi } +
|
||||
listOfNotNull(symbolProvider.getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name))?.fir?.psi)
|
||||
}
|
||||
is FirFile -> {
|
||||
if (expression.getNonStrictParentOfType<KtPackageDirective>() != null) {
|
||||
// Special: package reference in the middle of package directive
|
||||
return listOf(expression)
|
||||
}
|
||||
return listOfNotNull(fir.psi)
|
||||
}
|
||||
is FirArrayOfCall -> {
|
||||
// We can't yet find PsiElement for arrayOf, intArrayOf, etc.
|
||||
return emptyList()
|
||||
}
|
||||
is FirErrorNamedReference -> {
|
||||
return emptyList()
|
||||
}
|
||||
else -> {
|
||||
// Handle situation when we're in the middle/beginning of qualifier
|
||||
// <caret>A.B.C.foo() or A.<caret>B.C.foo()
|
||||
// NB: in this case we get some parent FIR, like FirBlock, FirProperty, FirFunction or the like
|
||||
var parent = expression.parent as? KtDotQualifiedExpression
|
||||
var unresolvedCounter = 1
|
||||
while (parent != null) {
|
||||
val selectorExpression = parent.selectorExpression ?: break
|
||||
if (selectorExpression === expression) {
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
continue
|
||||
}
|
||||
val parentFir = selectorExpression.getOrBuildFir(state)
|
||||
if (parentFir is FirResolvedQualifier) {
|
||||
var classId = parentFir.classId
|
||||
while (unresolvedCounter > 0) {
|
||||
unresolvedCounter--
|
||||
classId = classId?.outerClassId
|
||||
}
|
||||
return listOfNotNull(classId?.toTargetPsi(session))
|
||||
}
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
unresolvedCounter++
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class KotlinReferenceResolver : ResolveCache.PolyVariantResolver<AbstractKtReference<KtElement>> {
|
||||
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
|
||||
|
||||
private fun resolveToPsiElements(ref: AbstractKtReference<KtElement>): Collection<PsiElement> {
|
||||
if (FirResolution.enabled) {
|
||||
return FirReferenceResolveHelper.resolveToPsiElements(ref)
|
||||
}
|
||||
val bindingContext = ref.expression.analyze(BodyResolveMode.PARTIAL)
|
||||
return resolveToPsiElements(ref, bindingContext, ref.getTargetDescriptors(bindingContext))
|
||||
}
|
||||
|
||||
private fun resolveToPsiElements(
|
||||
ref: AbstractKtReference<KtElement>,
|
||||
context: BindingContext,
|
||||
targetDescriptors: Collection<DeclarationDescriptor>
|
||||
): Collection<PsiElement> {
|
||||
if (targetDescriptors.isNotEmpty()) {
|
||||
return targetDescriptors.flatMap { target -> resolveToPsiElements(ref, target) }.toSet()
|
||||
}
|
||||
|
||||
val labelTargets = getLabelTargets(ref, context)
|
||||
if (labelTargets != null) {
|
||||
return labelTargets
|
||||
}
|
||||
|
||||
return Collections.emptySet()
|
||||
}
|
||||
|
||||
private fun resolveToPsiElements(
|
||||
ref: AbstractKtReference<KtElement>,
|
||||
targetDescriptor: DeclarationDescriptor
|
||||
): Collection<PsiElement> {
|
||||
return if (targetDescriptor is PackageViewDescriptor) {
|
||||
val psiFacade = JavaPsiFacade.getInstance(ref.expression.project)
|
||||
val fqName = targetDescriptor.fqName.asString()
|
||||
listOfNotNull(psiFacade.findPackage(fqName))
|
||||
} else {
|
||||
DescriptorToSourceUtilsIde.getAllDeclarations(ref.expression.project, targetDescriptor, ref.expression.resolveScope)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLabelTargets(ref: AbstractKtReference<KtElement>, context: BindingContext): Collection<PsiElement>? {
|
||||
val reference = ref.expression as? KtReferenceExpression ?: return null
|
||||
val labelTarget = context[BindingContext.LABEL_TARGET, reference]
|
||||
if (labelTarget != null) {
|
||||
return listOf(labelTarget)
|
||||
}
|
||||
return context[BindingContext.AMBIGUOUS_LABEL_TARGET, reference]
|
||||
}
|
||||
|
||||
override fun resolve(ref: AbstractKtReference<KtElement>, incompleteCode: Boolean): Array<ResolveResult> {
|
||||
return runWithCancellationCheck {
|
||||
val resolveToPsiElements = resolveToPsiElements(ref)
|
||||
resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val KOTLIN_RESOLVER = KotlinReferenceResolver()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class KtSimpleReference<T : KtReferenceExpression>(expression: T) : AbstractKtReference<T>(expression) {
|
||||
override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context)
|
||||
fun KtReference.resolveToDescriptors(bindingContext: BindingContext): Collection<DeclarationDescriptor> {
|
||||
if (this !is KtDescriptorsBasedReference) {
|
||||
error("Reference $this should be KtDescriptorsBasedReference but was ${this::class}")
|
||||
}
|
||||
return resolveToDescriptors(bindingContext)
|
||||
}
|
||||
|
||||
abstract class KtMultiReference<T : KtElement>(expression: T) : AbstractKtReference<T>(expression)
|
||||
|
||||
object KotlinDescriptorsBasedReferenceResolver : ResolveCache.PolyVariantResolver<KtReference> {
|
||||
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
|
||||
|
||||
private fun resolveToPsiElements(ref: KtDescriptorsBasedReference): Collection<PsiElement> {
|
||||
val bindingContext = ref.element.analyze(BodyResolveMode.PARTIAL)
|
||||
return resolveToPsiElements(ref, bindingContext, ref.getTargetDescriptors(bindingContext))
|
||||
}
|
||||
|
||||
private fun resolveToPsiElements(
|
||||
ref: KtDescriptorsBasedReference,
|
||||
context: BindingContext,
|
||||
targetDescriptors: Collection<DeclarationDescriptor>
|
||||
): Collection<PsiElement> {
|
||||
if (targetDescriptors.isNotEmpty()) {
|
||||
return targetDescriptors.flatMap { target -> resolveToPsiElements(ref, target) }.toSet()
|
||||
}
|
||||
|
||||
val labelTargets = getLabelTargets(ref, context)
|
||||
if (labelTargets != null) {
|
||||
return labelTargets
|
||||
}
|
||||
|
||||
return Collections.emptySet()
|
||||
}
|
||||
|
||||
private fun resolveToPsiElements(
|
||||
ref: KtDescriptorsBasedReference,
|
||||
targetDescriptor: DeclarationDescriptor
|
||||
): Collection<PsiElement> {
|
||||
return if (targetDescriptor is PackageViewDescriptor) {
|
||||
val psiFacade = JavaPsiFacade.getInstance(ref.element.project)
|
||||
val fqName = targetDescriptor.fqName.asString()
|
||||
listOfNotNull(psiFacade.findPackage(fqName))
|
||||
} else {
|
||||
DescriptorToSourceUtilsIde.getAllDeclarations(ref.element.project, targetDescriptor, ref.element.resolveScope)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLabelTargets(ref: KtDescriptorsBasedReference, context: BindingContext): Collection<PsiElement>? {
|
||||
val reference = ref.element as? KtReferenceExpression ?: return null
|
||||
val labelTarget = context[BindingContext.LABEL_TARGET, reference]
|
||||
if (labelTarget != null) {
|
||||
return listOf(labelTarget)
|
||||
}
|
||||
return context[BindingContext.AMBIGUOUS_LABEL_TARGET, reference]
|
||||
}
|
||||
|
||||
override fun resolve(ref: KtReference, incompleteCode: Boolean): Array<ResolveResult> {
|
||||
return runWithCancellationCheck {
|
||||
val resolveToPsiElements = resolveToPsiElements(ref as KtDescriptorsBasedReference)
|
||||
resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.references
|
||||
import com.intellij.openapi.extensions.Extensions
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import com.intellij.util.SmartList
|
||||
@@ -33,15 +34,24 @@ import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
|
||||
import org.jetbrains.kotlin.resolve.ImportedFromObjectCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
|
||||
class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleReference<KtSimpleNameExpression>(expression) {
|
||||
class KtSimpleNameReferenceDescriptorsImpl(
|
||||
expression: KtSimpleNameExpression
|
||||
) : KtSimpleNameReference(expression), KtDescriptorsBasedReference {
|
||||
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean =
|
||||
canBeReferenceTo(candidateTarget)
|
||||
|
||||
override fun isReferenceToWithoutExtensionChecking(candidateTarget: PsiElement): Boolean =
|
||||
matchesTarget(candidateTarget)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
return SmartList<DeclarationDescriptor>().apply {
|
||||
// Replace Java property with its accessor(s)
|
||||
for (descriptor in super.getTargetDescriptors(context)) {
|
||||
for (descriptor in expression.getReferenceTargets(context)) {
|
||||
val sizeBefore = size
|
||||
|
||||
if (descriptor !is JavaPropertyDescriptor) {
|
||||
@@ -71,7 +81,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
|
||||
if (extension.isReferenceTo(this, element)) return true
|
||||
}
|
||||
|
||||
return super.isReferenceTo(element)
|
||||
return super<KtDescriptorsBasedReference>.isReferenceTo(element)
|
||||
}
|
||||
|
||||
override fun getRangeInElement(): TextRange {
|
||||
@@ -141,23 +151,18 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
|
||||
return expression
|
||||
}
|
||||
|
||||
enum class ShorteningMode {
|
||||
NO_SHORTENING,
|
||||
DELAYED_SHORTENING,
|
||||
FORCED_SHORTENING
|
||||
}
|
||||
|
||||
// By default reference binding is delayed
|
||||
override fun bindToElement(element: PsiElement): PsiElement =
|
||||
bindToElement(element, ShorteningMode.DELAYED_SHORTENING)
|
||||
|
||||
fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement =
|
||||
override fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement =
|
||||
element.getKotlinFqName()?.let { fqName -> bindToFqName(fqName, shorteningMode, element) } ?: expression
|
||||
|
||||
fun bindToFqName(
|
||||
override fun bindToFqName(
|
||||
fqName: FqName,
|
||||
shorteningMode: ShorteningMode = ShorteningMode.DELAYED_SHORTENING,
|
||||
targetElement: PsiElement? = null
|
||||
shorteningMode: ShorteningMode,
|
||||
targetElement: PsiElement?
|
||||
): PsiElement {
|
||||
val expression = expression
|
||||
if (fqName.isRoot) return expression
|
||||
@@ -289,7 +294,7 @@ class KtSimpleNameReference(expression: KtSimpleNameExpression) : KtSimpleRefere
|
||||
return listOf(element.getReferencedNameAsName())
|
||||
}
|
||||
|
||||
fun getImportAlias(): KtImportAlias? {
|
||||
override fun getImportAlias(): KtImportAlias? {
|
||||
fun DeclarationDescriptor.unwrap() = if (this is ImportedFromObjectCallableDescriptor<*>) callableFromObject else this
|
||||
|
||||
val element = element
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
|
||||
class ReadWriteAccessCheckerDescriptorsImpl : ReadWriteAccessChecker {
|
||||
override fun readWriteAccessWithFullExpressionByResolve(assignment: KtBinaryExpression): Pair<ReferenceAccess, KtExpression> {
|
||||
val resolvedCall = assignment.resolveToCall() ?: return ReferenceAccess.READ_WRITE to assignment
|
||||
if (!resolvedCall.isReallySuccess()) return ReferenceAccess.READ_WRITE to assignment
|
||||
return if (resolvedCall.resultingDescriptor.name in OperatorConventions.ASSIGNMENT_OPERATIONS.values)
|
||||
ReferenceAccess.READ to assignment
|
||||
else
|
||||
ReferenceAccess.READ_WRITE to assignment
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -22,14 +20,22 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.getReferenceTargets
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) :
|
||||
KtSimpleReference<KtNameReferenceExpression>(expression) {
|
||||
class SyntheticPropertyAccessorReferenceDescriptorImpl(
|
||||
expression: KtNameReferenceExpression,
|
||||
getter: Boolean
|
||||
) : SyntheticPropertyAccessorReference(expression, getter), KtDescriptorsBasedReference {
|
||||
override fun isReferenceTo(element: PsiElement): Boolean =
|
||||
super<SyntheticPropertyAccessorReference>.isReferenceTo(element)
|
||||
|
||||
override fun additionalIsReferenceToChecker(element: PsiElement): Boolean = matchesTarget(element)
|
||||
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
val descriptors = super.getTargetDescriptors(context)
|
||||
val descriptors = expression.getReferenceTargets(context)
|
||||
if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList()
|
||||
|
||||
val result = SmartList<FunctionDescriptor>()
|
||||
@@ -45,23 +51,6 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
|
||||
return result
|
||||
}
|
||||
|
||||
override fun isReferenceTo(element: PsiElement): Boolean {
|
||||
if (element !is PsiMethod || !isAccessorName(element.name)) return false
|
||||
if (!getter && expression.readWriteAccess(true) == ReferenceAccess.READ) return false
|
||||
return super.isReferenceTo(element)
|
||||
}
|
||||
|
||||
private fun isAccessorName(name: String): Boolean {
|
||||
if (getter) {
|
||||
return name.startsWith("get") || name.startsWith("is")
|
||||
}
|
||||
return name.startsWith("set")
|
||||
}
|
||||
|
||||
override fun getRangeInElement() = TextRange(0, expression.textLength)
|
||||
|
||||
override fun canRename() = true
|
||||
|
||||
private fun renameByPropertyName(newName: String): PsiElement? {
|
||||
val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName)
|
||||
expression.getReferencedNameElement().replace(nameIdentifier)
|
||||
@@ -183,7 +172,4 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
|
||||
|
||||
override val resolvesByNames: Collection<Name>
|
||||
get() = listOf(element.getReferencedNameAsName())
|
||||
|
||||
class Getter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, true)
|
||||
class Setter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, false)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.intentions.OperatorToFunctionIntention
|
||||
import org.jetbrains.kotlin.idea.kdoc.KDocReference
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFunctionShortNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinPropertyShortNameIndex
|
||||
@@ -221,22 +220,6 @@ fun AbstractKtReference<out KtExpression>.renameImplicitConventionalCall(newName
|
||||
return newExpression
|
||||
}
|
||||
|
||||
val KtSimpleNameExpression.mainReference: KtSimpleNameReference
|
||||
get() = references.firstIsInstance()
|
||||
|
||||
val KtReferenceExpression.mainReference: KtReference
|
||||
get() = if (this is KtSimpleNameExpression) mainReference else references.firstIsInstance<KtReference>()
|
||||
|
||||
val KDocName.mainReference: KDocReference
|
||||
get() = references.firstIsInstance()
|
||||
|
||||
val KtElement.mainReference: KtReference?
|
||||
get() = when (this) {
|
||||
is KtReferenceExpression -> mainReference
|
||||
is KDocName -> mainReference
|
||||
else -> references.firstIsInstanceOrNull<KtReference>()
|
||||
}
|
||||
|
||||
fun KtElement.resolveMainReferenceToDescriptors(): Collection<DeclarationDescriptor> {
|
||||
val bindingContext = analyze(BodyResolveMode.PARTIAL)
|
||||
return mainReference?.resolveToDescriptors(bindingContext) ?: emptyList()
|
||||
@@ -248,46 +231,6 @@ fun PsiReference.getImportAlias(): KtImportAlias? {
|
||||
|
||||
// ----------- Read/write access -----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) {
|
||||
READ(true, false), WRITE(false, true), READ_WRITE(true, true)
|
||||
}
|
||||
|
||||
fun KtExpression.readWriteAccess(useResolveForReadWrite: Boolean) = readWriteAccessWithFullExpression(useResolveForReadWrite).first
|
||||
|
||||
fun KtExpression.readWriteAccessWithFullExpression(useResolveForReadWrite: Boolean): Pair<ReferenceAccess, KtExpression> {
|
||||
var expression = getQualifiedExpressionForSelectorOrThis()
|
||||
loop@ while (true) {
|
||||
when (val parent = expression.parent) {
|
||||
is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression
|
||||
else -> break@loop
|
||||
}
|
||||
}
|
||||
|
||||
val assignment = expression.getAssignmentByLHS()
|
||||
if (assignment != null) {
|
||||
when (assignment.operationToken) {
|
||||
KtTokens.EQ -> return ReferenceAccess.WRITE to assignment
|
||||
|
||||
else -> {
|
||||
if (!useResolveForReadWrite) return ReferenceAccess.READ_WRITE to assignment
|
||||
|
||||
val resolvedCall = assignment.resolveToCall() ?: return ReferenceAccess.READ_WRITE to assignment
|
||||
if (!resolvedCall.isReallySuccess()) return ReferenceAccess.READ_WRITE to assignment
|
||||
return if (resolvedCall.resultingDescriptor.name in OperatorConventions.ASSIGNMENT_OPERATIONS.values)
|
||||
ReferenceAccess.READ to assignment
|
||||
else
|
||||
ReferenceAccess.READ_WRITE to assignment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val unaryExpression = expression.parent as? KtUnaryExpression
|
||||
return if (unaryExpression != null && unaryExpression.operationToken in constant { setOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS) })
|
||||
ReferenceAccess.READ_WRITE to unaryExpression
|
||||
else
|
||||
ReferenceAccess.READ to expression
|
||||
}
|
||||
|
||||
fun KtReference.canBeResolvedViaImport(target: DeclarationDescriptor, bindingContext: BindingContext): Boolean {
|
||||
if (this is KDocReference) {
|
||||
val qualifier = element.getQualifier() ?: return true
|
||||
|
||||
@@ -16,6 +16,7 @@ dependencies {
|
||||
compile(project(":compiler:util"))
|
||||
compile(project(":idea:ide-common"))
|
||||
compile(project(":idea:idea-jps-common"))
|
||||
compile(project(":idea:idea-frontend-independent"))
|
||||
compile(project(":kotlin-util-klib-metadata"))
|
||||
compile(project(":plugins:android-extensions-compiler"))
|
||||
compile(project(":kotlin-scripting-compiler-impl"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
|
||||
import org.jetbrains.kotlin.idea.imports.getImportableTargets
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
|
||||
import org.jetbrains.kotlin.idea.util.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.idea.references.resolveToDescriptors
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.resolve.frontendService
|
||||
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstanceToExpression
|
||||
@@ -158,8 +159,6 @@ fun KtCallableDeclaration.canOmitDeclaredType(initializerOrBodyExpression: KtExp
|
||||
return canChangeTypeToSubtype && expressionType.isSubtypeOf(declaredType)
|
||||
}
|
||||
|
||||
fun String.unquote(): String = KtPsiUtil.unquoteIdentifier(this)
|
||||
|
||||
fun FqName.quoteSegmentsIfNeeded(): String {
|
||||
return pathSegments().joinToString(".") { it.asString().quoteIfNeeded() }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -45,14 +45,6 @@ import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
inline fun <reified T : PsiElement> PsiElement.replaced(newElement: T): T {
|
||||
val result = replace(newElement)
|
||||
return result as? T ?: (result as KtParenthesizedExpression).expression as T
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : PsiElement> T.copied(): T = copy() as T
|
||||
|
||||
fun KtLambdaArgument.moveInsideParentheses(bindingContext: BindingContext): KtCallExpression {
|
||||
val ktExpression = this.getArgumentExpression()
|
||||
?: throw KotlinExceptionWithAttachments("no argument expression for $this")
|
||||
|
||||
@@ -4,52 +4,26 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompileOnly(toolsJar())
|
||||
testRuntimeOnly(toolsJar())
|
||||
compile(project(":idea:idea-frontend-fir"))
|
||||
compile(project(":idea:formatter"))
|
||||
compile(intellijDep())
|
||||
compile(intellijCoreDep())
|
||||
|
||||
testRuntimeOnly(intellijPluginDep("gradle"))
|
||||
testCompile(project(":idea"))
|
||||
// <temp>
|
||||
compile(project(":idea:idea-core"))
|
||||
compile(project(":idea"))
|
||||
// </temp>
|
||||
|
||||
testCompile(toolsJar())
|
||||
testCompile(projectTests(":idea"))
|
||||
testCompile(projectTests(":compiler:tests-common"))
|
||||
testCompile(projectTests(":idea:idea-test-framework")) { isTransitive = false }
|
||||
testCompile(projectTests(":idea:idea-test-framework"))
|
||||
testCompile(project(":kotlin-test:kotlin-test-junit"))
|
||||
testCompile(commonDep("junit:junit"))
|
||||
|
||||
testCompileOnly(intellijDep())
|
||||
testRuntime(intellijDep())
|
||||
|
||||
if (Platform[191].orLower()) {
|
||||
testRuntimeOnly(intellijPluginDep("Groovy"))
|
||||
}
|
||||
Platform[192].orHigher {
|
||||
testCompileOnly(intellijPluginDep("java"))
|
||||
testRuntime(intellijPluginDep("java"))
|
||||
compile(intellijPluginDep("java"))
|
||||
}
|
||||
|
||||
testRuntime(intellijRuntimeAnnotations())
|
||||
testRuntime(project(":plugins:kapt3-idea")) { isTransitive = false }
|
||||
testRuntime(project(":kotlin-reflect"))
|
||||
testRuntime(project(":kotlin-preloader"))
|
||||
|
||||
testCompile(project(":kotlin-sam-with-receiver-compiler-plugin")) { isTransitive = false }
|
||||
|
||||
testRuntime(project(":plugins:android-extensions-compiler"))
|
||||
testRuntimeOnly(project(":kotlin-android-extensions-runtime")) // TODO: fix import (workaround for jps build)
|
||||
testRuntime(project(":plugins:android-extensions-ide")) { isTransitive = false }
|
||||
testRuntime(project(":allopen-ide-plugin")) { isTransitive = false }
|
||||
testRuntime(project(":kotlin-allopen-compiler-plugin"))
|
||||
testRuntime(project(":noarg-ide-plugin")) { isTransitive = false }
|
||||
testRuntime(project(":kotlin-noarg-compiler-plugin"))
|
||||
testRuntime(project(":plugins:annotation-based-compiler-plugins-ide-support")) { isTransitive = false }
|
||||
testRuntime(project(":kotlin-scripting-idea")) { isTransitive = false }
|
||||
testRuntime(project(":kotlin-scripting-compiler-impl"))
|
||||
testRuntime(project(":sam-with-receiver-ide-plugin")) { isTransitive = false }
|
||||
testRuntime(project(":kotlinx-serialization-compiler-plugin"))
|
||||
testRuntime(project(":kotlinx-serialization-ide-plugin")) { isTransitive = false }
|
||||
testRuntime(project(":idea:idea-android")) { isTransitive = false }
|
||||
testRuntime(project(":plugins:lint")) { isTransitive = false }
|
||||
testRuntime(project(":plugins:uast-kotlin"))
|
||||
testRuntime(project(":nj2k:nj2k-services")) { isTransitive = false }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -57,9 +31,11 @@ sourceSets {
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
projectTest(parallel = true) {
|
||||
dependsOn(":dist")
|
||||
workingDir = rootDir
|
||||
if (rootProject.findProperty("idea.fir.plugin") == "true") {
|
||||
projectTest(parallel = true) {
|
||||
dependsOn(":dist")
|
||||
workingDir = rootDir
|
||||
}
|
||||
}
|
||||
|
||||
testsJar()
|
||||
testsJar()
|
||||
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFirPsiCheckerTest : AbstractPsiCheckerTest() {
|
||||
override fun isFirPlugin(): Boolean = true
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
FirResolution.enabled = true
|
||||
|
||||
@@ -650,118 +650,6 @@ public class FirPsiCheckerTestGenerated extends AbstractFirPsiCheckerTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/checker/duplicateJvmSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DuplicateJvmSignature extends AbstractFirPsiCheckerTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInDuplicateJvmSignature() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/checker/duplicateJvmSignature"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/checker/duplicateJvmSignature/fields")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Fields extends AbstractFirPsiCheckerTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInFields() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/checker/duplicateJvmSignature/fields"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("classObjectCopiedFieldObject.kt")
|
||||
public void testClassObjectCopiedFieldObject() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/fields/classObjectCopiedFieldObject.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/checker/duplicateJvmSignature/functionAndProperty")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class FunctionAndProperty extends AbstractFirPsiCheckerTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInFunctionAndProperty() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/checker/duplicateJvmSignature/functionAndProperty"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("ambiguous.kt")
|
||||
public void testAmbiguous() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/ambiguous.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("class.kt")
|
||||
public void testClass() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/class.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classObject.kt")
|
||||
public void testClassObject() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/classObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("localClass.kt")
|
||||
public void testLocalClass() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/localClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nestedClass.kt")
|
||||
public void testNestedClass() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/nestedClass.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("object.kt")
|
||||
public void testObject() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/object.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("objectExpression.kt")
|
||||
public void testObjectExpression() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/objectExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevel.kt")
|
||||
public void testTopLevel() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/topLevel.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelMultifileRuntime.kt")
|
||||
public void testTopLevelMultifileRuntime() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/topLevelMultifileRuntime.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("trait.kt")
|
||||
public void testTrait() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/functionAndProperty/trait.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/checker/duplicateJvmSignature/traitImpl")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class TraitImpl extends AbstractFirPsiCheckerTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInTraitImpl() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/checker/duplicateJvmSignature/traitImpl"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("twoTraits.kt")
|
||||
public void testTwoTraits() throws Exception {
|
||||
runTest("idea/testData/checker/duplicateJvmSignature/traitImpl/twoTraits.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/checker/infos")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.idea.jsonUtils.getString
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -31,6 +30,8 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractFirLazyResolveTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||
override fun isFirPlugin(): Boolean = true
|
||||
|
||||
override fun getProjectDescriptor(): LightProjectDescriptor {
|
||||
if (KotlinTestUtils.isAllFilesPresentTest(getTestName(false))) return super.getProjectDescriptor()
|
||||
val testFile = File(testDataPath, fileName())
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiManager
|
||||
@@ -47,7 +49,6 @@ import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromDirStructure
|
||||
import org.jetbrains.kotlin.idea.stubs.AbstractMultiModuleTest
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestJdkKind
|
||||
@@ -202,3 +203,4 @@ abstract class AbstractFirMultiModuleResolveTest : AbstractMultiModuleTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.idea.fir
|
||||
import org.jetbrains.kotlin.idea.AbstractResolveElementCacheTest
|
||||
|
||||
class FirResolveStateTest : AbstractResolveElementCacheTest() {
|
||||
override fun isFirPlugin(): Boolean = true
|
||||
|
||||
fun testSimpleStateCaching() {
|
||||
doTest {
|
||||
val firstStatement = statements[0]
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir
|
||||
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
|
||||
internal fun Project.allModules() = ModuleManager.getInstance(this).modules.toList()
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter
|
||||
|
||||
import org.jetbrains.kotlin.idea.test.ProjectDescriptorWithStdlibSources
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
|
||||
abstract class AbstractFirHighlightingTest : AbstractHighlightingTest() {
|
||||
override fun getDefaultProjectDescriptor() = ProjectDescriptorWithStdlibSources.INSTANCE
|
||||
|
||||
override fun isFirPlugin() = true
|
||||
|
||||
override fun checkHighlighting(fileText: String) {
|
||||
val doComparison = !InTextDirectivesUtils.isDirectiveDefined(myFixture.file.text, "IGNORE_FIR")
|
||||
val checkInfos = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_INFOS_PREFIX);
|
||||
|
||||
try {
|
||||
// warnings are not supported yet
|
||||
myFixture.checkHighlighting(/* checkWarnings= */ false, checkInfos, /* checkWeakWarnings= */ false)
|
||||
} catch (e: Throwable) {
|
||||
if (doComparison) throw e
|
||||
return
|
||||
}
|
||||
if (!doComparison) {
|
||||
throw AssertionError("Looks like test is passing, please remove IGNORE_FIR")
|
||||
}
|
||||
}
|
||||
}
|
||||
253
idea/idea-fir/tests/org/jetbrains/kotlin/idea/highlighter/FirHighlightingTestGenerated.java
generated
Normal file
253
idea/idea-fir/tests/org/jetbrains/kotlin/idea/highlighter/FirHighlightingTestGenerated.java
generated
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/highlighter")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class FirHighlightingTestGenerated extends AbstractFirHighlightingTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInHighlighter() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/highlighter"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("Annotations.kt")
|
||||
public void testAnnotations() throws Exception {
|
||||
runTest("idea/testData/highlighter/Annotations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("AutoCreatedItParameter.kt")
|
||||
public void testAutoCreatedItParameter() throws Exception {
|
||||
runTest("idea/testData/highlighter/AutoCreatedItParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Destructuring.kt")
|
||||
public void testDestructuring() throws Exception {
|
||||
runTest("idea/testData/highlighter/Destructuring.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Dynamic.kt")
|
||||
public void testDynamic() throws Exception {
|
||||
runTest("idea/testData/highlighter/Dynamic.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Enums.kt")
|
||||
public void testEnums() throws Exception {
|
||||
runTest("idea/testData/highlighter/Enums.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Field.kt")
|
||||
public void testField() throws Exception {
|
||||
runTest("idea/testData/highlighter/Field.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Functions.kt")
|
||||
public void testFunctions() throws Exception {
|
||||
runTest("idea/testData/highlighter/Functions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InvokeCall.kt")
|
||||
public void testInvokeCall() throws Exception {
|
||||
runTest("idea/testData/highlighter/InvokeCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("JavaTypes.kt")
|
||||
public void testJavaTypes() throws Exception {
|
||||
runTest("idea/testData/highlighter/JavaTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KDoc.kt")
|
||||
public void testKDoc() throws Exception {
|
||||
runTest("idea/testData/highlighter/KDoc.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("KotlinInjection.kt")
|
||||
public void testKotlinInjection() throws Exception {
|
||||
runTest("idea/testData/highlighter/KotlinInjection.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Labels.kt")
|
||||
public void testLabels() throws Exception {
|
||||
runTest("idea/testData/highlighter/Labels.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("NamedArguments.kt")
|
||||
public void testNamedArguments() throws Exception {
|
||||
runTest("idea/testData/highlighter/NamedArguments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("NonNullAssertion.kt")
|
||||
public void testNonNullAssertion() throws Exception {
|
||||
runTest("idea/testData/highlighter/NonNullAssertion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Object.kt")
|
||||
public void testObject() throws Exception {
|
||||
runTest("idea/testData/highlighter/Object.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("PropertiesWithPropertyDeclarations.kt")
|
||||
public void testPropertiesWithPropertyDeclarations() throws Exception {
|
||||
runTest("idea/testData/highlighter/PropertiesWithPropertyDeclarations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("SmartCast.kt")
|
||||
public void testSmartCast() throws Exception {
|
||||
runTest("idea/testData/highlighter/SmartCast.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Suspend.kt")
|
||||
public void testSuspend() throws Exception {
|
||||
runTest("idea/testData/highlighter/Suspend.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("SyntheticExtensionProperty.kt")
|
||||
public void testSyntheticExtensionProperty() throws Exception {
|
||||
runTest("idea/testData/highlighter/SyntheticExtensionProperty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Todo.kt")
|
||||
public void testTodo() throws Exception {
|
||||
runTest("idea/testData/highlighter/Todo.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelDestructuring.kt")
|
||||
public void testTopLevelDestructuring() throws Exception {
|
||||
runTest("idea/testData/highlighter/TopLevelDestructuring.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("TopLevelOpenSuspendFun.kt")
|
||||
public void testTopLevelOpenSuspendFun() throws Exception {
|
||||
runTest("idea/testData/highlighter/TopLevelOpenSuspendFun.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("TypeAlias.kt")
|
||||
public void testTypeAlias() throws Exception {
|
||||
runTest("idea/testData/highlighter/TypeAlias.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("TypesAndAnnotations.kt")
|
||||
public void testTypesAndAnnotations() throws Exception {
|
||||
runTest("idea/testData/highlighter/TypesAndAnnotations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Variables.kt")
|
||||
public void testVariables() throws Exception {
|
||||
runTest("idea/testData/highlighter/Variables.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("VariablesAsFunctions.kt")
|
||||
public void testVariablesAsFunctions() throws Exception {
|
||||
runTest("idea/testData/highlighter/VariablesAsFunctions.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("idea/testData/highlighter/deprecated")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Deprecated extends AbstractFirHighlightingTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInDeprecated() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/highlighter/deprecated"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("Class.kt")
|
||||
public void testClass() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Class.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ClassObject.kt")
|
||||
public void testClassObject() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/ClassObject.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Constructor.kt")
|
||||
public void testConstructor() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Constructor.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ExtensionFunction.kt")
|
||||
public void testExtensionFunction() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/ExtensionFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Function.kt")
|
||||
public void testFunction() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Function.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Get.kt")
|
||||
public void testGet() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Get.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Getter.kt")
|
||||
public void testGetter() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Getter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Inc.kt")
|
||||
public void testInc() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Inc.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Invalid.kt")
|
||||
public void testInvalid() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Invalid.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Invoke.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Operation.kt")
|
||||
public void testOperation() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Operation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Property.kt")
|
||||
public void testProperty() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Property.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("RangeTo.kt")
|
||||
public void testRangeTo() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/RangeTo.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Setter.kt")
|
||||
public void testSetter() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Setter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("SuperCall.kt")
|
||||
public void testSuperCall() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/SuperCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Trait.kt")
|
||||
public void testTrait() throws Exception {
|
||||
runTest("idea/testData/highlighter/deprecated/Trait.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.idea.resolve
|
||||
|
||||
import com.intellij.testFramework.LightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.completion.test.configureWithExtraFile
|
||||
import org.jetbrains.kotlin.idea.fir.FirResolution
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||
import org.jetbrains.kotlin.idea.test.ProjectDescriptorWithStdlibSources
|
||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||
|
||||
abstract class AbstractFirReferenceResolveTest : AbstractReferenceResolveTest() {
|
||||
override fun isFirPlugin(): Boolean = true
|
||||
|
||||
override fun getProjectDescriptor(): KotlinLightProjectDescriptor =
|
||||
KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE_FULL_JDK
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
FirResolution.enabled = true
|
||||
|
||||
34
idea/idea-frontend-api/build.gradle.kts
Normal file
34
idea/idea-frontend-api/build.gradle.kts
Normal file
@@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":compiler:psi"))
|
||||
compileOnly(project(":compiler:frontend"))
|
||||
compileOnly(project(":core:type-system"))
|
||||
compileOnly(project(":idea:idea-frontend-independent"))
|
||||
compileOnly(project(":compiler:psi"))
|
||||
compileOnly(intellijCoreDep())
|
||||
compileOnly(intellijDep())
|
||||
|
||||
Platform[191].orLower {
|
||||
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
||||
}
|
||||
|
||||
Platform[192].orHigher {
|
||||
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
testsJar()
|
||||
|
||||
projectTest {
|
||||
dependsOn(":dist")
|
||||
workingDir = rootDir
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.frontend.api
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
|
||||
sealed class CallInfo {
|
||||
abstract val isSuspendCall: Boolean
|
||||
abstract val targetFunction: PsiElement?
|
||||
}
|
||||
|
||||
data class VariableAsFunctionCallInfo(val target: PsiElement, override val isSuspendCall: Boolean) : CallInfo() {
|
||||
override val targetFunction: PsiElement? = null
|
||||
}
|
||||
|
||||
data class VariableAsFunctionLikeCallInfo(val target: PsiElement, val invokeFunction: KtNamedFunction) : CallInfo() {
|
||||
override val isSuspendCall: Boolean get() = invokeFunction.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
||||
override val targetFunction: PsiElement? get() = invokeFunction
|
||||
}
|
||||
|
||||
// SimpleFunctionCallInfo
|
||||
|
||||
sealed class SimpleFunctionCallInfo : CallInfo() {
|
||||
abstract override val targetFunction: PsiElement
|
||||
}
|
||||
|
||||
data class SimpleKtFunctionCallInfo(override val targetFunction: KtNamedFunction) : SimpleFunctionCallInfo() {
|
||||
override val isSuspendCall: Boolean get() = targetFunction.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
||||
}
|
||||
|
||||
data class SimpleJavaFunctionCallInfo(override val targetFunction: PsiMethod) : SimpleFunctionCallInfo() {
|
||||
override val isSuspendCall: Boolean = false
|
||||
}
|
||||
|
||||
|
||||
// ConstructorCallInfo
|
||||
|
||||
//TODO
|
||||
object ConstructorCallInfo : CallInfo() {
|
||||
// abstract val targetConstructor: PsiElement?
|
||||
final override val isSuspendCall: Boolean = false
|
||||
override val targetFunction: PsiElement? = null
|
||||
}
|
||||
|
||||
//data class SimpleKtConstructorCallInfo(override val targetConstructor: KtConstructor<*>) : ConstructorCallInfo()
|
||||
|
||||
//data class SimpleJavaConstructorCallInfo(override val targetConstructor: PsiMethod) : ConstructorCallInfo()
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.frontend.api
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
|
||||
abstract class FrontendAnalysisSession {
|
||||
abstract fun getSmartCastedToTypes(expression: KtExpression): Collection<KotlinTypeMarker>?
|
||||
|
||||
abstract fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast>
|
||||
|
||||
abstract fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KotlinTypeMarker?
|
||||
|
||||
abstract fun renderType(type: KotlinTypeMarker): String
|
||||
|
||||
abstract fun getKtExpressionType(expression: KtExpression): KotlinTypeMarker?
|
||||
|
||||
abstract fun isSubclassOf(klass: KtClassOrObject, superClassId: ClassId): Boolean
|
||||
|
||||
abstract fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic>
|
||||
|
||||
abstract fun resolveCall(call: KtCallExpression): CallInfo?
|
||||
|
||||
abstract fun resolveCall(call: KtBinaryExpression): CallInfo?
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.frontend.api
|
||||
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
|
||||
data class ImplicitReceiverSmartCast(val types: Collection<KotlinTypeMarker>, val kind: ImplicitReceiverSmartcastKind)
|
||||
|
||||
enum class ImplicitReceiverSmartcastKind {
|
||||
DISPATCH, EXTENSION
|
||||
}
|
||||
48
idea/idea-frontend-fir/build.gradle.kts
Normal file
48
idea/idea-frontend-fir/build.gradle.kts
Normal file
@@ -0,0 +1,48 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(project(":compiler:psi"))
|
||||
compile(project(":idea:idea-frontend-independent"))
|
||||
compile(project(":idea:idea-frontend-api"))
|
||||
compile(project(":idea:idea-core"))
|
||||
compile(project(":compiler:fir:fir2ir"))
|
||||
compile(project(":compiler:fir:resolve"))
|
||||
compile(project(":compiler:fir:checkers"))
|
||||
compile(project(":compiler:fir:java"))
|
||||
compile(project(":compiler:fir:jvm"))
|
||||
compile(intellijDep())
|
||||
compile(intellijCoreDep())
|
||||
|
||||
// <temp>
|
||||
compile(project(":idea:idea-core"))
|
||||
// </temp>
|
||||
|
||||
testCompile(toolsJar())
|
||||
testCompile(projectTests(":idea"))
|
||||
testCompile(projectTests(":compiler:tests-common"))
|
||||
testCompile(projectTests(":idea:idea-test-framework"))
|
||||
testCompile(project(":kotlin-test:kotlin-test-junit"))
|
||||
testCompile(commonDep("junit:junit"))
|
||||
|
||||
Platform[192].orHigher {
|
||||
compile(intellijPluginDep("java"))
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
if (rootProject.findProperty("idea.fir.plugin") == "true") {
|
||||
projectTest {
|
||||
dependsOn(":dist")
|
||||
workingDir = rootDir
|
||||
}
|
||||
}
|
||||
|
||||
testsJar()
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelTypeAliasFqNameIndex
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
|
||||
|
||||
//todo introduce LibraryModificationTracker based cache?
|
||||
object FirIdeDeserializedDeclarationSourceProvider {
|
||||
fun findPsi(fir: FirElement, project: Project): PsiElement? {
|
||||
return when (fir) {
|
||||
is FirSimpleFunction -> provideSourceForFunction(fir, project)
|
||||
is FirProperty -> provideSourceForProperty(fir, project)
|
||||
is FirClass<*> -> provideSourceForClass(fir, project)
|
||||
is FirTypeAlias -> provideSourceForTypeAlias(fir, project)
|
||||
is FirConstructor -> provideSourceForConstructor(fir, project)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun provideSourceForFunction(
|
||||
function: FirSimpleFunction,
|
||||
project: Project
|
||||
): PsiElement? {
|
||||
val candidates = if (function.isTopLevel) {
|
||||
KotlinTopLevelFunctionFqnNameIndex.getInstance().get(
|
||||
function.symbol.callableId.asFqNameForDebugInfo().asString(),
|
||||
project,
|
||||
function.scope(project)
|
||||
).filter(KtNamedFunction::isCompiled)
|
||||
} else {
|
||||
function.containingKtClass(project)?.body?.functions
|
||||
?.filter { it.name == function.name.asString() && it.isCompiled() }
|
||||
.orEmpty()
|
||||
}
|
||||
|
||||
return function.chooseCorrespondingPsi(candidates)
|
||||
}
|
||||
|
||||
private fun provideSourceForProperty(property: FirProperty, project: Project): PsiElement? {
|
||||
val candidates = if (property.isTopLevel) {
|
||||
KotlinTopLevelFunctionFqnNameIndex.getInstance().get(
|
||||
property.symbol.callableId.asFqNameForDebugInfo().asString(),
|
||||
project,
|
||||
property.scope(project)
|
||||
)
|
||||
} else {
|
||||
property.containingKtClass(project)?.declarations
|
||||
?.filter { it.name == property.name.asString() }
|
||||
.orEmpty()
|
||||
}
|
||||
|
||||
return candidates.firstOrNull(KtElement::isCompiled)
|
||||
}
|
||||
|
||||
private fun provideSourceForClass(klass: FirClass<*>, project: Project): PsiElement? =
|
||||
classByClassId(klass.symbol.classId, klass.scope(project), project)
|
||||
|
||||
private fun provideSourceForTypeAlias(alias: FirTypeAlias, project: Project): PsiElement? {
|
||||
val candidates = KotlinTopLevelTypeAliasFqNameIndex.getInstance().get(
|
||||
alias.symbol.classId.asStringForUsingInIndexes(),
|
||||
project,
|
||||
alias.scope(project)
|
||||
)
|
||||
return candidates.firstOrNull(KtElement::isCompiled)
|
||||
}
|
||||
|
||||
private fun provideSourceForConstructor(
|
||||
constructor: FirConstructor,
|
||||
project: Project
|
||||
): PsiElement? {
|
||||
val containingKtClass = constructor.containingKtClass(project) ?: return null
|
||||
if (constructor.isPrimary) return containingKtClass.primaryConstructor
|
||||
|
||||
return constructor.chooseCorrespondingPsi(containingKtClass.secondaryConstructors)
|
||||
}
|
||||
|
||||
private fun FirFunction<*>.chooseCorrespondingPsi(
|
||||
candidates: Collection<KtFunction>
|
||||
): KtFunction? {
|
||||
if (candidates.isEmpty()) return null
|
||||
for (candidate in candidates) {
|
||||
assert(candidate.isCompiled()) {
|
||||
"Candidate should be decompiled from metadata because it should have fqName types as we don't use resolve here"
|
||||
}
|
||||
if (KtDeclarationAndFirDeclarationEqualityChecker.representsTheSameDeclaration(candidate, this)) {
|
||||
return candidate
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun FirDeclaration.scope(project: Project): GlobalSearchScope {
|
||||
return GlobalSearchScope.allScope(project)
|
||||
/* TODO:
|
||||
val session = session as? FirLibrarySession
|
||||
return session?.scope ?: GlobalSearchScope.allScope(project)*/
|
||||
}
|
||||
|
||||
private fun FirCallableDeclaration<*>.containingKtClass(project: Project): KtClassOrObject? =
|
||||
symbol.callableId.classId?.let { classByClassId(it, scope(project), project) }
|
||||
|
||||
private fun classByClassId(classId: ClassId, scope: GlobalSearchScope, project: Project): KtClassOrObject? {
|
||||
val fqName = classId.asStringForUsingInIndexes().let { classIdMapping[it] ?: it }
|
||||
return KotlinFullClassNameIndex.getInstance().get(
|
||||
fqName,
|
||||
project,
|
||||
scope
|
||||
).firstOrNull(KtElement::isCompiled)
|
||||
}
|
||||
|
||||
private val FirCallableDeclaration<*>.isTopLevel
|
||||
get() = symbol.callableId.className == null
|
||||
|
||||
private fun ClassId.asStringForUsingInIndexes() = asString().replace('/', '.')
|
||||
|
||||
private val classIdMapping = (0..23).associate { i ->
|
||||
"kotlin.Function$i" to "kotlin.jvm.functions.Function$i"
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtElement.isCompiled(): Boolean = containingKtFile.isCompiled
|
||||
|
||||
fun FirElement.findPsi(project: Project): PsiElement? =
|
||||
psi ?: FirIdeDeserializedDeclarationSourceProvider.findPsi(this, project)
|
||||
|
||||
fun FirElement.findPsi(session: FirSession): PsiElement? =
|
||||
findPsi(session.sessionProvider!!.project)
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.idea.fir
|
||||
import com.intellij.openapi.components.ServiceManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.ModificationTracker
|
||||
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
||||
import org.jetbrains.kotlin.analyzer.TrackableModuleInfo
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
@@ -60,5 +59,5 @@ class FirIdeResolveStateServiceImpl(val project: Project) : FirIdeResolveStateSe
|
||||
}
|
||||
|
||||
override val fallbackModificationTracker: ModificationTracker? =
|
||||
KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
|
||||
org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService.getInstance(project).outOfBlockModificationTracker
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,8 @@ import org.jetbrains.kotlin.fir.extensions.BunchOfRegisteredExtensions
|
||||
import org.jetbrains.kotlin.fir.extensions.extensionService
|
||||
import org.jetbrains.kotlin.fir.extensions.registerExtensions
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.idea.caches.project.IdeaModuleInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.LibrarySourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.ModuleSourceInfo
|
||||
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
@@ -27,13 +29,18 @@ interface FirModuleResolveState {
|
||||
val sessionProvider: FirProjectSessionProvider
|
||||
|
||||
fun getSession(psi: KtElement): FirSession {
|
||||
val moduleInfo = psi.getModuleInfo() as ModuleSourceInfo
|
||||
val moduleInfo = psi.getModuleInfo()
|
||||
return getSession(psi.project, moduleInfo)
|
||||
}
|
||||
|
||||
fun getSession(project: Project, moduleInfo: ModuleSourceInfo): FirSession {
|
||||
fun getSession(project: Project, moduleInfo: IdeaModuleInfo): FirSession {
|
||||
sessionProvider.getSession(moduleInfo)?.let { return it }
|
||||
return synchronized(moduleInfo.module) {
|
||||
val lock = when (moduleInfo) {
|
||||
is ModuleSourceInfo -> moduleInfo.module
|
||||
is LibrarySourceInfo -> moduleInfo.library
|
||||
else -> TODO(moduleInfo.toString())
|
||||
}
|
||||
return synchronized(lock) {
|
||||
val session = sessionProvider.getSession(moduleInfo) ?: FirIdeJavaModuleBasedSession(
|
||||
project, moduleInfo, sessionProvider, moduleInfo.contentScope()
|
||||
).also { moduleBasedSession ->
|
||||
@@ -89,7 +96,7 @@ class FirModuleResolveStateImpl(override val sessionProvider: FirProjectSessionP
|
||||
}
|
||||
|
||||
override fun record(psi: KtElement, fir: FirElement) {
|
||||
cache[psi] = fir
|
||||
cache.putIfAbsent(psi, fir)
|
||||
}
|
||||
|
||||
override fun record(psi: KtElement, diagnostic: Diagnostic) {
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir
|
||||
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.util.containingNonLocalDeclaration
|
||||
|
||||
private val FirResolvePhase.stubMode: Boolean
|
||||
get() = this <= FirResolvePhase.DECLARATIONS
|
||||
@@ -52,7 +52,8 @@ private fun FirFile.findCallableMember(
|
||||
return provider.getClassDeclaredCallableSymbols(ClassId(packageFqName, klassFqName, false), declName)
|
||||
.find { symbol: FirCallableSymbol<*> ->
|
||||
symbol.fir.psi == callableMember
|
||||
}?.fir ?: error("Cannot find FIR callable declaration ${CallableId(packageFqName, klassFqName, declName)}")
|
||||
}?.fir
|
||||
?: error("Cannot find FIR callable declaration ${CallableId(packageFqName, klassFqName, declName)}")
|
||||
}
|
||||
// NB: not sure it's correct to use member scope provider from here (because of possible changes)
|
||||
val memberScope = FirPackageMemberScope(this.packageFqName, session)
|
||||
@@ -224,12 +225,35 @@ private class FirDesignatedBodyResolveTransformerForIDE(
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified E : FirElement> KtElement.getOrBuildFirSafe(
|
||||
state: FirModuleResolveState,
|
||||
phase: FirResolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
) = getOrBuildFir(state, phase) as? E
|
||||
|
||||
|
||||
private fun KtElement.getNonLocalContainingDeclarationWithFqName(): KtDeclaration? {
|
||||
var container = parent
|
||||
while (container != null && container !is KtFile) {
|
||||
if (container is KtDeclaration
|
||||
&& (container is KtClassOrObject || container is KtDeclarationWithBody)
|
||||
&& !KtPsiUtil.isLocal(container)
|
||||
&& container.name != null
|
||||
&& container !is KtEnumEntry
|
||||
&& container.containingClassOrObject !is KtEnumEntry
|
||||
) {
|
||||
return container
|
||||
}
|
||||
container = container.parent
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun KtElement.getOrBuildFir(
|
||||
state: FirModuleResolveState,
|
||||
phase: FirResolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
): FirElement {
|
||||
val containerFir: FirDeclaration =
|
||||
when (val container = this.containingNonLocalDeclaration()) {
|
||||
when (val container = getNonLocalContainingDeclarationWithFqName()) {
|
||||
is KtCallableDeclaration -> container.getOrBuildFir(state, phase)
|
||||
is KtClassOrObject -> container.getOrBuildFir(state, phase)
|
||||
null -> containingKtFile.getOrBuildFir(state, phase)
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.idea.references.KtReference
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
fun FirFunctionCall.isImplicitFunctionCall(): Boolean {
|
||||
if (dispatchReceiver !is FirQualifiedAccessExpression) return false
|
||||
val resolvedCalleeSymbol = (calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
||||
return (resolvedCalleeSymbol as? FirNamedFunctionSymbol)?.fir?.name == OperatorNameConventions.INVOKE
|
||||
}
|
||||
|
||||
fun FirFunctionCall.getCalleeSymbol(): FirBasedSymbol<*>? =
|
||||
calleeReference.getResolvedSymbolOfNameReference()
|
||||
|
||||
fun FirReference.getResolvedSymbolOfNameReference(): FirBasedSymbol<*>? =
|
||||
(this as? FirResolvedNamedReference)?.resolvedSymbol
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir
|
||||
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.builder.RawFirBuilder
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
// TODO replace with structural type comparision?
|
||||
object KtDeclarationAndFirDeclarationEqualityChecker {
|
||||
fun representsTheSameDeclaration(psi: KtFunction, fir: FirFunction<*>): Boolean {
|
||||
if ((fir.receiverTypeRef != null) != (psi.receiverTypeReference != null)) return false
|
||||
if (fir.receiverTypeRef != null
|
||||
&& !isTheSameTypes(
|
||||
psi.receiverTypeReference!!,
|
||||
fir.receiverTypeRef!!,
|
||||
fir.session,
|
||||
isVararg = false
|
||||
)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
if (fir.valueParameters.size != psi.valueParameters.size) return false
|
||||
fir.valueParameters.zip(psi.valueParameters) { expectedParameter, candidateParameter ->
|
||||
if (expectedParameter.name.toString() != candidateParameter.name) return false
|
||||
if (expectedParameter.isVararg != candidateParameter.isVarArg) return false
|
||||
val candidateParameterType = candidateParameter.typeReference ?: return false
|
||||
if (!isTheSameTypes(
|
||||
candidateParameterType,
|
||||
expectedParameter.returnTypeRef,
|
||||
fir.session,
|
||||
isVararg = expectedParameter.isVararg
|
||||
)
|
||||
) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun FirTypeRef.renderTypeAsKotlinType(isVararg: Boolean = false): String {
|
||||
val rendered = when (this) {
|
||||
is FirResolvedTypeRef -> type.renderTypeAsKotlinType()
|
||||
is FirUserTypeRef -> {
|
||||
val renderedQualifier = qualifier.joinToString(separator = ".") { part ->
|
||||
buildString {
|
||||
append(part.name)
|
||||
if (part.typeArguments.isNotEmpty()) {
|
||||
part.typeArguments.joinTo(this, prefix = "<", postfix = ">") { it.renderTypeAsKotlinType() }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isMarkedNullable) "$renderedQualifier?" else renderedQualifier
|
||||
}
|
||||
is FirFunctionTypeRef -> {
|
||||
val classId = if (isSuspend) {
|
||||
KotlinBuiltIns.getSuspendFunctionClassId(parametersCount)
|
||||
} else {
|
||||
KotlinBuiltIns.getFunctionClassId(parametersCount)
|
||||
}
|
||||
buildString {
|
||||
append(classId.asSingleFqName().toString())
|
||||
val parameters = buildList {
|
||||
receiverTypeRef?.let(::add)
|
||||
valueParameters.mapTo(this) { it.returnTypeRef }
|
||||
returnTypeRef.let(::add)
|
||||
}
|
||||
if (parameters.isNotEmpty()) {
|
||||
append(parameters.joinToString(prefix = "<", postfix = ">") { it.renderTypeAsKotlinType() })
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> error("Invalid type reference $this")
|
||||
}
|
||||
return if (isVararg) {
|
||||
"kotlin.Array<out $rendered>"
|
||||
} else {
|
||||
rendered
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirTypeProjection.renderTypeAsKotlinType() = when (this) {
|
||||
is FirStarProjection -> "*"
|
||||
is FirTypeProjectionWithVariance -> buildString {
|
||||
append(variance.label)
|
||||
if (variance != Variance.INVARIANT) {
|
||||
append(" ")
|
||||
}
|
||||
append(typeRef.renderTypeAsKotlinType())
|
||||
}
|
||||
else -> error("Invalid type projection $this")
|
||||
}
|
||||
|
||||
private fun isTheSameTypes(
|
||||
psiTypeReference: KtTypeReference,
|
||||
coneTypeReference: FirTypeRef,
|
||||
session: FirSession,
|
||||
isVararg: Boolean
|
||||
): Boolean =
|
||||
psiTypeReference.toKotlinTypReference(session).renderTypeAsKotlinType(isVararg) == coneTypeReference.renderTypeAsKotlinType()
|
||||
|
||||
private fun KtTypeReference.toKotlinTypReference(session: FirSession): FirTypeRef {
|
||||
// Maybe resolve all types here to not to work with FirTypeRef directly
|
||||
return RawFirBuilder(session, DummyScopeProvider, stubMode = true).buildTypeReference(this)
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.renderTypeAsKotlinType(): String {
|
||||
val rendered = when (this) {
|
||||
is ConeClassLikeType -> buildString {
|
||||
append(lookupTag.classId.asString())
|
||||
if (typeArguments.isNotEmpty()) {
|
||||
append(typeArguments.joinToString(prefix = "<", postfix = ">", separator = ", ") { it.renderTypeAsKotlinType() })
|
||||
}
|
||||
}
|
||||
is ConeTypeVariableType -> lookupTag.name.asString()
|
||||
is ConeLookupTagBasedType -> lookupTag.name.asString()
|
||||
is ConeFlexibleType -> {
|
||||
// Can be present as return type
|
||||
"${lowerBound.renderTypeAsKotlinType()}..${upperBound.renderTypeAsKotlinType()}"
|
||||
}
|
||||
else -> error("Type $this should not be present in Kotlin declaration")
|
||||
}.replace('/', '.')
|
||||
return rendered + nullability.suffix
|
||||
}
|
||||
|
||||
private fun ConeTypeProjection.renderTypeAsKotlinType(): String = when (this) {
|
||||
ConeStarProjection -> "*"
|
||||
is ConeKotlinTypeProjectionIn -> "in ${type.renderTypeAsKotlinType()}"
|
||||
is ConeKotlinTypeProjectionOut -> "out ${type.renderTypeAsKotlinType()}"
|
||||
is ConeKotlinType -> renderTypeAsKotlinType()
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
internal fun renderPsi(ktFunction: KtFunction, session: FirSession): String = buildString {
|
||||
appendLine("receiver: ${ktFunction.receiverTypeReference?.toKotlinTypReference(session)?.renderTypeAsKotlinType()}")
|
||||
ktFunction.valueParameters.forEach { parameter ->
|
||||
appendLine("${parameter.name}: ${parameter.typeReference?.toKotlinTypReference(session)?.renderTypeAsKotlinType()}")
|
||||
}
|
||||
appendLine("return: ${ktFunction.typeReference?.toKotlinTypReference(session)?.renderTypeAsKotlinType()}")
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
internal fun renderFir(firFunction: FirFunction<*>): String = buildString {
|
||||
appendLine("receiver: ${firFunction.receiverTypeRef?.renderTypeAsKotlinType()}")
|
||||
firFunction.valueParameters.forEach { parameter ->
|
||||
appendLine("${parameter.name}: ${parameter.returnTypeRef.renderTypeAsKotlinType()}")
|
||||
}
|
||||
appendLine("return: ${firFunction.returnTypeRef.renderTypeAsKotlinType()}")
|
||||
}
|
||||
|
||||
private object DummyScopeProvider : FirScopeProvider() {
|
||||
override fun getUseSiteMemberScope(klass: FirClass<*>, useSiteSession: FirSession, scopeSession: ScopeSession): FirScope {
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
|
||||
override fun getStaticMemberScopeForCallables(
|
||||
klass: FirClass<*>,
|
||||
useSiteSession: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
): FirScope? {
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
|
||||
override fun getNestedClassifierScope(klass: FirClass<*>, useSiteSession: FirSession, scopeSession: ScopeSession): FirScope? {
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
|
||||
private fun shouldNotBeCalled(): Nothing =
|
||||
error("Should not be called in RawFirBuilder while converting KtTypeReference")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.frontend.api.fir
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiMethod
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.idea.fir.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.*
|
||||
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper
|
||||
import org.jetbrains.kotlin.idea.references.FirReferenceResolveHelper.toTargetPsi
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
|
||||
class AnalysisSessionFirImpl internal constructor(
|
||||
private val state: FirModuleResolveState
|
||||
) : FrontendAnalysisSession() {
|
||||
|
||||
override fun getSmartCastedToTypes(expression: KtExpression): Collection<KotlinTypeMarker>? {
|
||||
// TODO filter out not used smartcasts
|
||||
return (expression.toFir() as? FirExpressionWithSmartcast)?.typesFromSmartCast
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
override fun getImplicitReceiverSmartCasts(expression: KtExpression): Collection<ImplicitReceiverSmartCast> {
|
||||
// TODO filter out not used smartcasts
|
||||
val qualifiedExpression = expression.getOrBuildFir(state) as? FirQualifiedAccessExpression ?: return emptyList()
|
||||
if (qualifiedExpression.dispatchReceiver !is FirExpressionWithSmartcast
|
||||
&& qualifiedExpression.extensionReceiver !is FirExpressionWithSmartcast
|
||||
) return emptyList()
|
||||
return buildList {
|
||||
(qualifiedExpression.dispatchReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
|
||||
ImplicitReceiverSmartCast(smartCasted.typesFromSmartCast, ImplicitReceiverSmartcastKind.DISPATCH)
|
||||
}?.let(::add)
|
||||
(qualifiedExpression.extensionReceiver as? FirExpressionWithSmartcast)?.let { smartCasted ->
|
||||
ImplicitReceiverSmartCast(smartCasted.typesFromSmartCast, ImplicitReceiverSmartcastKind.EXTENSION)
|
||||
}?.let(::add)
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderType(type: KotlinTypeMarker): String =
|
||||
type.asConeType().render()
|
||||
|
||||
override fun getReturnTypeForKtDeclaration(declaration: KtDeclaration): KotlinTypeMarker? =
|
||||
declaration.toFir<FirCallableDeclaration<*>>()?.returnTypeRef?.coneTypeSafe()
|
||||
|
||||
override fun getKtExpressionType(expression: KtExpression): ConeKotlinType? =
|
||||
expression.toFir<FirExpression>()?.typeRef?.coneTypeSafe()
|
||||
|
||||
override fun isSubclassOf(klass: KtClassOrObject, superClassId: ClassId): Boolean {
|
||||
var result = false
|
||||
forEachSubClass(klass.toFir() ?: return false) { type ->
|
||||
result = result || type.firClassLike(state.getSession(klass))?.symbol?.classId == superClassId
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getDiagnosticsForElement(element: KtElement): Collection<Diagnostic> {
|
||||
element.containingKtFile.getOrBuildFirWithDiagnostics(state)
|
||||
return state.getDiagnostics(element)
|
||||
}
|
||||
|
||||
override fun resolveCall(call: KtBinaryExpression): CallInfo? {
|
||||
val firCall = call.toFir<FirFunctionCall>() ?: return null
|
||||
return resolveCall(firCall, call)
|
||||
}
|
||||
|
||||
override fun resolveCall(call: KtCallExpression): CallInfo? {
|
||||
val firCall = call.toFir<FirFunctionCall>() ?: return null
|
||||
return resolveCall(firCall, call)
|
||||
}
|
||||
|
||||
private fun resolveCall(firCall: FirFunctionCall, callExpression: KtExpression): CallInfo? {
|
||||
val session = callExpression.getSession()
|
||||
val resolvedFunctionPsi = firCall.calleeReference.toTargetPsi(session)
|
||||
val resolvedCalleeSymbol = (firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
||||
return when {
|
||||
resolvedCalleeSymbol is FirConstructorSymbol -> {
|
||||
ConstructorCallInfo//todo use proper constructor info
|
||||
}
|
||||
firCall.dispatchReceiver is FirQualifiedAccessExpression && firCall.isImplicitFunctionCall() -> {
|
||||
val target = with(FirReferenceResolveHelper) {
|
||||
val calleeReference = (firCall.dispatchReceiver as FirQualifiedAccessExpression).calleeReference
|
||||
calleeReference.toTargetPsi(session)
|
||||
}
|
||||
when (target) {
|
||||
null -> null
|
||||
is KtValVarKeywordOwner, is PsiField -> {
|
||||
val functionSymbol =
|
||||
(firCall.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol
|
||||
when (functionSymbol?.callableId) {
|
||||
null -> null
|
||||
in kotlinFunctionInvokeCallableIds -> VariableAsFunctionCallInfo(target, functionSymbol.fir.isSuspend)
|
||||
else -> (resolvedFunctionPsi as? KtNamedFunction)?.let { VariableAsFunctionLikeCallInfo(target, it) }
|
||||
}
|
||||
}
|
||||
else -> resolvedFunctionPsi?.asSimpleFunctionCall()
|
||||
}
|
||||
}
|
||||
else -> resolvedFunctionPsi?.asSimpleFunctionCall()
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.asSimpleFunctionCall() = when (this) {
|
||||
is KtNamedFunction -> SimpleKtFunctionCallInfo(this)
|
||||
is PsiMethod -> SimpleJavaFunctionCallInfo(this)
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun KtElement.getSession() = state.getSession(this)
|
||||
|
||||
private inline fun <reified F : FirElement> KtElement.toFir(phase: FirResolvePhase = FirResolvePhase.BODY_RESOLVE): F? =
|
||||
getOrBuildFir(state, phase) as? F
|
||||
|
||||
private fun forEachSubClass(firClass: FirClass<*>, action: (FirResolvedTypeRef) -> Unit) {
|
||||
firClass.superTypeRefs.forEach { superType ->
|
||||
(superType as? FirResolvedTypeRef)?.let(action)
|
||||
(superType.firClassLike(firClass.session) as? FirClass<*>?)?.let { forEachSubClass(it, action) }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun forElement(element: KtElement): FrontendAnalysisSession =
|
||||
AnalysisSessionFirImpl(element.firResolveState())
|
||||
|
||||
private fun KotlinTypeMarker.asConeType(): ConeKotlinType =
|
||||
this as? ConeKotlinType ?: error("$this should be ConeKotlinType")
|
||||
|
||||
private val kotlinFunctionInvokeCallableIds = (0..23).flatMapTo(hashSetOf()) { arity ->
|
||||
listOf(
|
||||
CallableId(KotlinBuiltIns.getFunctionClassId(arity), Name.identifier("invoke")),
|
||||
CallableId(KotlinBuiltIns.getSuspendFunctionClassId(arity), Name.identifier("invoke"))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter
|
||||
|
||||
import com.intellij.lang.jvm.JvmModifier
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import com.intellij.psi.*
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAbstract
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
|
||||
|
||||
internal fun textAttributesKeyForPropertyDeclaration(declaration: PsiElement): TextAttributesKey? = when (declaration) {
|
||||
is KtProperty -> textAttributesForKtPropertyDeclaration(declaration)
|
||||
is KtParameter -> textAttributesForKtParameterDeclaration(declaration)
|
||||
is PsiLocalVariable -> Colors.LOCAL_VARIABLE
|
||||
is PsiParameter -> Colors.PARAMETER
|
||||
is PsiField -> Colors.INSTANCE_PROPERTY
|
||||
else -> null
|
||||
}
|
||||
|
||||
internal fun textAttributesForKtParameterDeclaration(parameter: KtParameter) =
|
||||
if (parameter.valOrVarKeyword != null) Colors.INSTANCE_PROPERTY
|
||||
else Colors.PARAMETER
|
||||
|
||||
internal fun textAttributesForKtPropertyDeclaration(property: KtProperty): TextAttributesKey? = when {
|
||||
property.isExtensionDeclaration() -> Colors.EXTENSION_PROPERTY
|
||||
property.isLocal -> Colors.LOCAL_VARIABLE
|
||||
property.isTopLevel -> {
|
||||
if (property.isCustomPropertyDeclaration()) Colors.PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
|
||||
else Colors.PACKAGE_PROPERTY
|
||||
}
|
||||
else -> {
|
||||
if (property.isCustomPropertyDeclaration()) Colors.INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
|
||||
else Colors.INSTANCE_PROPERTY
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtProperty.isCustomPropertyDeclaration() =
|
||||
getter?.bodyExpression != null || setter?.bodyExpression != null
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
internal fun textAttributesKeyForTypeDeclaration(declaration: PsiElement): TextAttributesKey? = when {
|
||||
declaration is KtTypeParameter || declaration is PsiTypeParameter -> Colors.TYPE_PARAMETER
|
||||
declaration is KtTypeAlias -> Colors.TYPE_ALIAS
|
||||
declaration is KtClass -> textAttributesForClass(declaration)
|
||||
declaration is PsiClass && declaration.isInterface && !declaration.isAnnotationType -> Colors.TRAIT
|
||||
declaration.isAnnotationClass() -> Colors.ANNOTATION
|
||||
declaration is KtObjectDeclaration -> Colors.OBJECT
|
||||
declaration is PsiEnumConstant -> Colors.ENUM_ENTRY
|
||||
declaration is PsiClass && declaration.hasModifier(JvmModifier.ABSTRACT) -> Colors.ABSTRACT_CLASS
|
||||
declaration is PsiClass -> Colors.CLASS
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun textAttributesForClass(klass: KtClass): TextAttributesKey = when {
|
||||
klass.isInterface() -> Colors.TRAIT
|
||||
klass.isAnnotation() -> Colors.ANNOTATION
|
||||
klass is KtEnumEntry -> Colors.ENUM_ENTRY
|
||||
klass.isAbstract() -> Colors.ABSTRACT_CLASS
|
||||
else -> Colors.CLASS
|
||||
}
|
||||
|
||||
internal fun PsiElement.isAnnotationClass() =
|
||||
this is KtClass && isAnnotation() || this is PsiClass && isAnnotationType
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
import org.jetbrains.kotlin.idea.highlighter.visitors.FirAfterResolveHighlightingVisitor
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
class KotlinFirPsiChecker : AbstractKotlinPsiChecker() {
|
||||
override fun shouldHighlight(file: KtFile): Boolean {
|
||||
return true // todo
|
||||
}
|
||||
|
||||
override fun annotateElement(element: PsiElement, containingFile: KtFile, holder: AnnotationHolder) {
|
||||
if (element !is KtElement) return
|
||||
val analysisSession = AnalysisSessionFirImpl.forElement(element)
|
||||
|
||||
highlightDiagnostics(element, analysisSession, holder)
|
||||
|
||||
FirAfterResolveHighlightingVisitor
|
||||
.createListOfVisitors(analysisSession, holder)
|
||||
.forEach(element::accept)
|
||||
}
|
||||
|
||||
private fun highlightDiagnostics(element: KtElement, analysisSession: FrontendAnalysisSession, holder: AnnotationHolder) {
|
||||
val diagnostics = analysisSession.getDiagnosticsForElement(element)
|
||||
if (diagnostics.isEmpty()) return
|
||||
|
||||
if (diagnostics.none(Diagnostic::isValid)) return
|
||||
|
||||
if (shouldHighlightErrors(element)) {
|
||||
highlightDiagnostics(diagnostics, holder)
|
||||
}
|
||||
}
|
||||
|
||||
private fun highlightDiagnostics(diagnostics: Collection<Diagnostic>, holder: AnnotationHolder) {
|
||||
diagnostics.groupBy { it.factory }.forEach { group -> registerDiagnosticAnnotations(group.value, holder) }
|
||||
}
|
||||
|
||||
private fun registerDiagnosticAnnotations(diagnostics: List<Diagnostic>, holder: AnnotationHolder) {
|
||||
assert(diagnostics.isNotEmpty())
|
||||
val diagnostic = diagnostics.first()
|
||||
|
||||
val ranges = diagnostic.textRanges
|
||||
|
||||
ranges.forEach { range ->
|
||||
diagnostics.forEach { diagnostic ->
|
||||
Diagnostic2Annotation.createAnnotation(
|
||||
diagnostic,
|
||||
range,
|
||||
holder,
|
||||
nonDefaultMessage = null,
|
||||
textAttributes = null,
|
||||
highlightType = null,
|
||||
renderMessage = IdeErrorMessages::render
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun shouldHighlightErrors(element: KtElement): Boolean {
|
||||
return true // todo
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter.visitors
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.psi.util.elementType
|
||||
import org.jetbrains.kotlin.idea.highlighter.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
|
||||
|
||||
internal class DeclarationHighlightingVisitor(holder: AnnotationHolder) : HighlightingVisitor(holder) {
|
||||
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
|
||||
highlightNamedDeclaration(typeAlias, Colors.TYPE_ALIAS)
|
||||
super.visitTypeAlias(typeAlias)
|
||||
}
|
||||
|
||||
override fun visitObjectDeclaration(declaration: KtObjectDeclaration) {
|
||||
highlightNamedDeclaration(declaration, Colors.OBJECT)
|
||||
super.visitObjectDeclaration(declaration)
|
||||
}
|
||||
|
||||
override fun visitClass(klass: KtClass) {
|
||||
highlightNamedDeclaration(klass, textAttributesForClass(klass))
|
||||
super.visitClass(klass)
|
||||
}
|
||||
|
||||
override fun visitProperty(property: KtProperty) {
|
||||
textAttributesForKtPropertyDeclaration(property)?.let { attributes ->
|
||||
highlightNamedDeclaration(property, attributes)
|
||||
}
|
||||
highlightMutability(property)
|
||||
super.visitProperty(property)
|
||||
}
|
||||
|
||||
override fun visitParameter(parameter: KtParameter) {
|
||||
textAttributesForKtParameterDeclaration(parameter)?.let { attributes ->
|
||||
highlightNamedDeclaration(parameter, attributes)
|
||||
}
|
||||
highlightMutability(parameter)
|
||||
super.visitParameter(parameter)
|
||||
}
|
||||
|
||||
|
||||
private fun <D> highlightMutability(declaration: D) where D : KtValVarKeywordOwner, D : KtNamedDeclaration {
|
||||
if (declaration.valOrVarKeyword?.elementType == KtTokens.VAR_KEYWORD) {
|
||||
highlightNamedDeclaration(declaration, Colors.MUTABLE_VARIABLE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DeclarationHighlightingExtension : BeforeResolveHighlightingExtension {
|
||||
override fun createVisitor(holder: AnnotationHolder): HighlightingVisitor =
|
||||
DeclarationHighlightingVisitor(holder)
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter.visitors
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle
|
||||
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.frontend.api.ImplicitReceiverSmartcastKind
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
internal class ExpressionsSmartcastHighlightingVisitor(
|
||||
analysisSession: FrontendAnalysisSession,
|
||||
holder: AnnotationHolder
|
||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||
override fun visitExpression(expression: KtExpression) {
|
||||
analysisSession.getImplicitReceiverSmartCasts(expression).forEach { (types, kind) ->
|
||||
val receiverName = when (kind) {
|
||||
ImplicitReceiverSmartcastKind.EXTENSION -> KotlinIdeaAnalysisBundle.message("extension.implicit.receiver")
|
||||
ImplicitReceiverSmartcastKind.DISPATCH -> KotlinIdeaAnalysisBundle.message("implicit.receiver")
|
||||
}
|
||||
|
||||
types.forEach { type ->
|
||||
createInfoAnnotation(
|
||||
expression,
|
||||
KotlinIdeaAnalysisBundle.message(
|
||||
"0.smart.cast.to.1",
|
||||
receiverName,
|
||||
analysisSession.renderType(type)
|
||||
)
|
||||
).textAttributes = org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors.SMART_CAST_RECEIVER
|
||||
}
|
||||
}
|
||||
analysisSession.getSmartCastedToTypes(expression)?.forEach { type ->
|
||||
createInfoAnnotation(
|
||||
getSmartCastTarget(expression),
|
||||
KotlinIdeaAnalysisBundle.message(
|
||||
"smart.cast.to.0",
|
||||
analysisSession.renderType(type)
|
||||
)
|
||||
).textAttributes = org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors.SMART_CAST_VALUE
|
||||
}
|
||||
|
||||
//todo smartcast to null
|
||||
|
||||
super.visitExpression(expression)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun getSmartCastTarget(expression: KtExpression): PsiElement {
|
||||
var target: PsiElement = expression
|
||||
if (target is KtParenthesizedExpression) {
|
||||
target = KtPsiUtil.deparenthesize(target) ?: expression
|
||||
}
|
||||
return when (target) {
|
||||
is KtIfExpression -> target.ifKeyword
|
||||
is KtWhenExpression -> target.whenKeyword
|
||||
is KtBinaryExpression -> target.operationReference
|
||||
else -> target
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter.visitors
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.highlighter.HighlightingVisitor
|
||||
|
||||
abstract class FirAfterResolveHighlightingVisitor(
|
||||
protected val analysisSession: FrontendAnalysisSession,
|
||||
protected val holder: AnnotationHolder
|
||||
) : HighlightingVisitor(holder) {
|
||||
|
||||
companion object {
|
||||
fun createListOfVisitors(
|
||||
analysisSession: FrontendAnalysisSession,
|
||||
holder: AnnotationHolder
|
||||
): List<FirAfterResolveHighlightingVisitor> = listOf(
|
||||
TypeHighlightingVisitor(analysisSession, holder),
|
||||
FunctionCallHighlightingVisitor(analysisSession, holder),
|
||||
ExpressionsSmartcastHighlightingVisitor(analysisSession, holder),
|
||||
VariableReferenceHighlightingVisitor(analysisSession, holder),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter.visitors
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||
import org.jetbrains.kotlin.idea.frontend.api.*
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.serialization.deserialization.KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
|
||||
|
||||
internal class FunctionCallHighlightingVisitor(
|
||||
analysisSession: FrontendAnalysisSession,
|
||||
holder: AnnotationHolder
|
||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||
override fun visitBinaryExpression(expression: KtBinaryExpression) {
|
||||
(expression.operationReference as? KtReferenceExpression)
|
||||
?.takeIf {
|
||||
// do not highlight assignment statement
|
||||
(it as? KtOperationReferenceExpression)?.operationSignTokenType != KtTokens.EQ
|
||||
}?.let { callee ->
|
||||
analysisSession.resolveCall(expression)
|
||||
?.takeIf { callInfo ->
|
||||
// ignore arithmetic-like operator calls
|
||||
(callInfo.targetFunction as? KtNamedFunction)?.hasModifier(KtTokens.OPERATOR_KEYWORD) != true
|
||||
}
|
||||
?.let { callInfo ->
|
||||
getTextAttributesForCal(callInfo)?.let { attributes ->
|
||||
highlightName(callee, attributes)
|
||||
}
|
||||
}
|
||||
}
|
||||
super.visitBinaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression) {
|
||||
expression.calleeExpression
|
||||
?.takeUnless { it is KtLambdaExpression }
|
||||
?.takeUnless { it is KtCallExpression /* KT-16159 */}
|
||||
?.let { callee ->
|
||||
analysisSession.resolveCall(expression)?.let { callInfo ->
|
||||
getTextAttributesForCal(callInfo)?.let { attributes ->
|
||||
highlightName(callee, attributes)
|
||||
}
|
||||
}
|
||||
}
|
||||
super.visitCallExpression(expression)
|
||||
}
|
||||
|
||||
private fun getTextAttributesForCal(callInfo: CallInfo): TextAttributesKey? = when {
|
||||
callInfo.isSuspendCall -> Colors.SUSPEND_FUNCTION_CALL
|
||||
callInfo is ConstructorCallInfo ->
|
||||
Colors.CONSTRUCTOR_CALL
|
||||
callInfo is SimpleKtFunctionCallInfo -> when {
|
||||
callInfo.targetFunction.getKotlinFqName() == KOTLIN_SUSPEND_BUILT_IN_FUNCTION_FQ_NAME ->Colors.KEYWORD
|
||||
callInfo.targetFunction.isExtensionDeclaration() -> Colors.EXTENSION_FUNCTION_CALL
|
||||
callInfo.targetFunction.parent is KtFile -> Colors.PACKAGE_FUNCTION_CALL
|
||||
else -> Colors.FUNCTION_CALL
|
||||
}
|
||||
callInfo is SimpleJavaFunctionCallInfo -> Colors.FUNCTION_CALL
|
||||
callInfo is VariableAsFunctionCallInfo -> Colors.VARIABLE_AS_FUNCTION_CALL
|
||||
callInfo is VariableAsFunctionLikeCallInfo -> Colors.VARIABLE_AS_FUNCTION_LIKE_CALL
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter.visitors
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.highlighter.NameHighlighter
|
||||
import org.jetbrains.kotlin.idea.highlighter.isAnnotationClass
|
||||
import org.jetbrains.kotlin.idea.highlighter.textAttributesKeyForTypeDeclaration
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
|
||||
|
||||
internal class TypeHighlightingVisitor(
|
||||
analysisSession: FrontendAnalysisSession,
|
||||
holder: AnnotationHolder
|
||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
if (!NameHighlighter.namesHighlightingEnabled) return
|
||||
if (expression.isCalleeExpression()) return
|
||||
val parent = expression.parent
|
||||
|
||||
if (parent is KtInstanceExpressionWithLabel) {
|
||||
// Do nothing: 'super' and 'this' are highlighted as a keyword
|
||||
return
|
||||
}
|
||||
val target = expression.mainReference.resolve() ?: return
|
||||
textAttributesKeyForTypeDeclaration(target)?.let { key ->
|
||||
if (expression.isConstructorCallReference() && key != Colors.ANNOTATION) {
|
||||
// Do not highlight constructor call as class reference
|
||||
return@let
|
||||
}
|
||||
highlightName(computeHighlightingRangeForUsage(expression, target), key)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun computeHighlightingRangeForUsage(expression: KtSimpleNameExpression, target: PsiElement): TextRange {
|
||||
val expressionRange = expression.textRange
|
||||
|
||||
if (!target.isAnnotationClass()) return expressionRange
|
||||
|
||||
// include '@' symbol if the reference is the first segment of KtAnnotationEntry
|
||||
// if "Deprecated" is highlighted then '@' should be highlighted too in "@Deprecated"
|
||||
val annotationEntry = PsiTreeUtil.getParentOfType(
|
||||
expression, KtAnnotationEntry::class.java, /* strict = */false, KtValueArgumentList::class.java
|
||||
)
|
||||
val atSymbol = annotationEntry?.atSymbol ?: return expressionRange
|
||||
return TextRange(atSymbol.textRange.startOffset, expression.textRange.endOffset)
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtSimpleNameExpression.isCalleeExpression() =
|
||||
(parent as? KtCallExpression)?.calleeExpression == this
|
||||
|
||||
private fun KtSimpleNameExpression.isConstructorCallReference(): Boolean {
|
||||
val type = parent as? KtUserType ?: return false
|
||||
val typeReference = type.parent as? KtTypeReference ?: return false
|
||||
val constructorCallee = typeReference.parent as? KtConstructorCalleeExpression ?: return false
|
||||
return constructorCallee.constructorReferenceExpression == this
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter.visitors
|
||||
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.PsiVariable
|
||||
import com.intellij.psi.util.elementType
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import org.jetbrains.kotlin.idea.KotlinIdeaAnalysisBundle
|
||||
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
|
||||
import org.jetbrains.kotlin.idea.highlighter.NameHighlighter
|
||||
import org.jetbrains.kotlin.idea.highlighter.textAttributesKeyForPropertyDeclaration
|
||||
import org.jetbrains.kotlin.idea.references.mainReference
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
|
||||
|
||||
internal class VariableReferenceHighlightingVisitor(
|
||||
analysisSession: FrontendAnalysisSession,
|
||||
holder: AnnotationHolder
|
||||
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
if (!NameHighlighter.namesHighlightingEnabled) return
|
||||
if (expression.isAssignmentReference()) return
|
||||
if (expression.parent is KtInstanceExpressionWithLabel) return
|
||||
|
||||
if (expression.isAutoCreatedItParameter()) {
|
||||
createInfoAnnotation(
|
||||
expression,
|
||||
Colors.FUNCTION_LITERAL_DEFAULT_PARAMETER,
|
||||
KotlinIdeaAnalysisBundle.message("automatically.declared.based.on.the.expected.type")
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val target = expression.mainReference.resolve()
|
||||
|
||||
when {
|
||||
target != null && expression.isBackingField(target) -> Colors.BACKING_FIELD_VARIABLE
|
||||
target is PsiMethod -> Colors.SYNTHETIC_EXTENSION_PROPERTY
|
||||
target != null -> textAttributesKeyForPropertyDeclaration(target)
|
||||
else -> null
|
||||
}?.let { attribute ->
|
||||
highlightName(expression, attribute)
|
||||
if (target?.isMutableVariable() == true) {
|
||||
highlightName(expression, Colors.MUTABLE_VARIABLE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun KtSimpleNameExpression.isAutoCreatedItParameter(): Boolean {
|
||||
return getReferencedName() == "it" // todo
|
||||
}
|
||||
}
|
||||
|
||||
private fun PsiElement.isMutableVariable() = when {
|
||||
this is KtValVarKeywordOwner && valOrVarKeyword?.elementType == KtTokens.VAR_KEYWORD -> true
|
||||
this is PsiVariable && !hasModifierProperty(PsiModifier.FINAL) -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun KtSimpleNameExpression.isAssignmentReference(): Boolean {
|
||||
if (this !is KtOperationReferenceExpression) return false
|
||||
return operationSignTokenType == KtTokens.EQ
|
||||
}
|
||||
|
||||
private fun KtSimpleNameExpression.isBackingField(target: PsiElement): Boolean {
|
||||
if (getReferencedName() != "field") return false
|
||||
if (target !is KtProperty) return false
|
||||
val accessor = parentOfType<KtPropertyAccessor>() ?: return false
|
||||
return accessor.parent == target
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.idea.fir.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
|
||||
interface FirKtReference : KtReference {
|
||||
fun getResolvedToPsi(
|
||||
analysisSession: AnalysisSessionFirImpl,
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState
|
||||
): Collection<PsiElement>
|
||||
|
||||
override val resolver get() = KtFirReferenceResolver
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.idea.fir.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
|
||||
object FirReferenceResolveHelper {
|
||||
fun FirResolvedTypeRef.toTargetPsi(session: FirSession): PsiElement? {
|
||||
val type = type as? ConeLookupTagBasedType ?: return null
|
||||
return (type.lookupTag.toSymbol(session) as? AbstractFirBasedSymbol<*>)?.fir?.findPsi(session)
|
||||
}
|
||||
|
||||
fun ClassId.toTargetPsi(session: FirSession, calleeReference: FirReference? = null): PsiElement? {
|
||||
val classLikeDeclaration = ConeClassLikeLookupTagImpl(this).toSymbol(session)?.fir
|
||||
if (classLikeDeclaration is FirRegularClass) {
|
||||
if (calleeReference is FirResolvedNamedReference) {
|
||||
val callee = calleeReference.resolvedSymbol.fir as? FirCallableMemberDeclaration
|
||||
// TODO: check callee owner directly?
|
||||
if (callee !is FirConstructor && callee?.isStatic != true) {
|
||||
classLikeDeclaration.companionObject?.let { return it.findPsi(session) }
|
||||
}
|
||||
}
|
||||
}
|
||||
return classLikeDeclaration?.findPsi(session)
|
||||
}
|
||||
|
||||
fun FirReference.toTargetPsi(session: FirSession): PsiElement? {
|
||||
return when (this) {
|
||||
is FirResolvedNamedReference -> {
|
||||
val targetFir = when (val symbol = resolvedSymbol) {
|
||||
is SyntheticPropertySymbol -> {
|
||||
val syntheticProperty = symbol.fir as FirSyntheticProperty
|
||||
if (syntheticProperty.getter.delegate.symbol.callableId == symbol.accessorId) {
|
||||
syntheticProperty.getter.delegate
|
||||
} else {
|
||||
syntheticProperty.setter!!.delegate
|
||||
}
|
||||
}
|
||||
else -> symbol.fir
|
||||
}
|
||||
targetFir.findPsi(session)
|
||||
}
|
||||
is FirResolvedCallableReference -> {
|
||||
resolvedSymbol.fir.findPsi(session)
|
||||
}
|
||||
is FirThisReference -> {
|
||||
boundSymbol?.fir?.findPsi(session)
|
||||
}
|
||||
is FirSuperReference -> {
|
||||
(superTypeRef as? FirResolvedTypeRef)?.toTargetPsi(session)
|
||||
}
|
||||
else -> {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun resolveSimpleNameReference(
|
||||
ref: KtSimpleNameReferenceFirImpl,
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState
|
||||
): Collection<PsiElement> {
|
||||
val expression = ref.expression
|
||||
when (val fir = expression.getOrBuildFir(state)) {
|
||||
is FirResolvable -> {
|
||||
val calleeReference =
|
||||
if (fir is FirFunctionCall
|
||||
&& fir.isImplicitFunctionCall()
|
||||
&& expression is KtNameReferenceExpression
|
||||
) {
|
||||
// we are resolving implicit invoke call, like
|
||||
// fun foo(a: () -> Unit) {
|
||||
// <expression>a</expression>()
|
||||
// }
|
||||
(fir.dispatchReceiver as FirQualifiedAccessExpression).calleeReference
|
||||
} else fir.calleeReference
|
||||
return listOfNotNull(calleeReference.toTargetPsi(session))
|
||||
}
|
||||
is FirResolvedTypeRef -> {
|
||||
return listOfNotNull(fir.toTargetPsi(session))
|
||||
}
|
||||
is FirResolvedQualifier -> {
|
||||
val classId = fir.classId ?: return emptyList()
|
||||
// Distinguish A.foo() from A(.Companion).foo()
|
||||
// Make expression.parent as? KtDotQualifiedExpression local function
|
||||
var parent = expression.parent as? KtDotQualifiedExpression
|
||||
while (parent != null) {
|
||||
val selectorExpression = parent.selectorExpression ?: break
|
||||
if (selectorExpression === expression) {
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
continue
|
||||
}
|
||||
val parentFir = selectorExpression.getOrBuildFir(state)
|
||||
if (parentFir is FirQualifiedAccess) {
|
||||
return listOfNotNull(classId.toTargetPsi(session, parentFir.calleeReference))
|
||||
}
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
}
|
||||
return listOfNotNull(classId.toTargetPsi(session))
|
||||
}
|
||||
is FirAnnotationCall -> {
|
||||
val type = fir.typeRef as? FirResolvedTypeRef ?: return emptyList()
|
||||
return listOfNotNull(type.toTargetPsi(session))
|
||||
}
|
||||
is FirResolvedImport -> {
|
||||
var parent = expression.parent
|
||||
while (parent is KtDotQualifiedExpression) {
|
||||
if (parent.selectorExpression !== expression) {
|
||||
// Special: package reference in the middle of import directive
|
||||
// import a.<caret>b.c.SomeClass
|
||||
// TODO: return reference to PsiPackage
|
||||
return listOf(expression)
|
||||
}
|
||||
parent = parent.parent
|
||||
}
|
||||
val classId = fir.resolvedClassId
|
||||
if (classId != null) {
|
||||
return listOfNotNull(classId.toTargetPsi(session))
|
||||
}
|
||||
val name = fir.importedName ?: return emptyList()
|
||||
val symbolProvider = session.firSymbolProvider
|
||||
return symbolProvider.getTopLevelCallableSymbols(fir.packageFqName, name)
|
||||
.mapNotNull { it.fir.findPsi(session) } +
|
||||
listOfNotNull(
|
||||
symbolProvider
|
||||
.getClassLikeSymbolByFqName(ClassId(fir.packageFqName, name))
|
||||
?.fir?.findPsi(session)
|
||||
)
|
||||
}
|
||||
is FirFile -> {
|
||||
if (expression.getNonStrictParentOfType<KtPackageDirective>() != null) {
|
||||
// Special: package reference in the middle of package directive
|
||||
return listOf(expression)
|
||||
}
|
||||
return listOfNotNull(fir.findPsi(session))
|
||||
}
|
||||
is FirArrayOfCall -> {
|
||||
// We can't yet find PsiElement for arrayOf, intArrayOf, etc.
|
||||
return emptyList()
|
||||
}
|
||||
is FirReturnExpression -> {
|
||||
return if (expression is KtLabelReferenceExpression) {
|
||||
listOfNotNull(fir.target.labeledElement.findPsi(session))
|
||||
} else emptyList()
|
||||
}
|
||||
is FirErrorNamedReference -> {
|
||||
return emptyList()
|
||||
}
|
||||
else -> {
|
||||
// Handle situation when we're in the middle/beginning of qualifier
|
||||
// <caret>A.B.C.foo() or A.<caret>B.C.foo()
|
||||
// NB: in this case we get some parent FIR, like FirBlock, FirProperty, FirFunction or the like
|
||||
var parent = expression.parent as? KtDotQualifiedExpression
|
||||
var unresolvedCounter = 1
|
||||
while (parent != null) {
|
||||
val selectorExpression = parent.selectorExpression ?: break
|
||||
if (selectorExpression === expression) {
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
continue
|
||||
}
|
||||
val parentFir = selectorExpression.getOrBuildFir(state)
|
||||
if (parentFir is FirResolvedQualifier) {
|
||||
var classId = parentFir.classId
|
||||
while (unresolvedCounter > 0) {
|
||||
unresolvedCounter--
|
||||
classId = classId?.outerClassId
|
||||
}
|
||||
return listOfNotNull(classId?.toTargetPsi(session))
|
||||
}
|
||||
parent = parent.parent as? KtDotQualifiedExpression
|
||||
unresolvedCounter++
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.idea.fir.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtImportAlias
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
|
||||
internal class KtSimpleNameReferenceFirImpl(
|
||||
expression: KtSimpleNameExpression
|
||||
) : KtSimpleNameReference(expression), FirKtReference {
|
||||
override fun getResolvedToPsi(
|
||||
analysisSession: AnalysisSessionFirImpl,
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState
|
||||
) = FirReferenceResolveHelper.resolveSimpleNameReference(this, session, state)
|
||||
|
||||
override fun doCanBeReferenceTo(candidateTarget: PsiElement): Boolean {
|
||||
return true // TODO
|
||||
}
|
||||
|
||||
override fun isReferenceToWithoutExtensionChecking(candidateTarget: PsiElement): Boolean {
|
||||
return resolve() == candidateTarget //todo
|
||||
}
|
||||
|
||||
override fun handleElementRename(newElementName: String): PsiElement? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun bindToElement(element: PsiElement, shorteningMode: ShorteningMode): PsiElement {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun bindToFqName(fqName: FqName, shorteningMode: ShorteningMode, targetElement: PsiElement?): PsiElement {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getImportAlias(): KtImportAlias? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override val resolver get() = KtFirReferenceResolver
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
class KotlinFirReferenceContributor : KotlinReferenceProviderContributor {
|
||||
override fun registerReferenceProviders(registrar: KotlinPsiReferenceRegistrar) {
|
||||
with(registrar) {
|
||||
registerProvider(factory = ::KtSimpleNameReferenceFirImpl)
|
||||
registerProvider(factory = ::KtForLoopInReferenceFirImpl)
|
||||
registerProvider(factory = ::KtInvokeFunctionReferenceFirImpl)
|
||||
registerProvider(factory = ::KtPropertyDelegationMethodsReferenceFirImpl)
|
||||
registerProvider(factory = ::KtDestructuringDeclarationReferenceFirImpl)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.idea.fir.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
import org.jetbrains.kotlin.psi.KtDestructuringDeclarationEntry
|
||||
|
||||
class KtDestructuringDeclarationReferenceFirImpl(
|
||||
element: KtDestructuringDeclarationEntry
|
||||
) : KtDestructuringDeclarationReference(element), FirKtReference {
|
||||
override fun canRename(): Boolean = false //todo
|
||||
|
||||
override fun getResolvedToPsi(
|
||||
analysisSession: AnalysisSessionFirImpl,
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState
|
||||
): Collection<PsiElement> {
|
||||
val fir = expression.getOrBuildFirSafe<FirProperty>(state) ?: return emptyList()
|
||||
val componentFunctionSymbol = (fir.initializer as? FirComponentCall)?.getCalleeSymbol() ?: return emptyList()
|
||||
return listOfNotNull(componentFunctionSymbol.fir.findPsi(session))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiElementResolveResult
|
||||
import com.intellij.psi.ResolveResult
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache
|
||||
import org.jetbrains.kotlin.idea.fir.firResolveState
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
|
||||
object KtFirReferenceResolver : ResolveCache.PolyVariantResolver<KtReference> {
|
||||
class KotlinResolveResult(element: PsiElement) : PsiElementResolveResult(element)
|
||||
|
||||
override fun resolve(ref: KtReference, incompleteCode: Boolean): Array<ResolveResult> {
|
||||
check(ref is FirKtReference) { "reference should be FirKtReference, but was ${ref::class}" }
|
||||
check(ref is AbstractKtReference<*>) { "reference should be AbstractKtReference, but was ${ref::class}" }
|
||||
val expression = ref.expression
|
||||
val state = expression.firResolveState()
|
||||
val session = state.getSession(expression)
|
||||
val analysisSession = AnalysisSessionFirImpl(state)
|
||||
val resolveToPsiElements = ref.getResolvedToPsi(analysisSession, session, state)
|
||||
return resolveToPsiElements.map { KotlinResolveResult(it) }.toTypedArray()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWhileLoop
|
||||
import org.jetbrains.kotlin.idea.fir.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.fir.findPsi
|
||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe
|
||||
import org.jetbrains.kotlin.idea.fir.getResolvedSymbolOfNameReference
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
import org.jetbrains.kotlin.psi.KtForExpression
|
||||
|
||||
open class KtForLoopInReferenceFirImpl(expression: KtForExpression) : KtForLoopInReference(expression), FirKtReference {
|
||||
override fun getResolvedToPsi(
|
||||
analysisSession: AnalysisSessionFirImpl,
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState
|
||||
): Collection<PsiElement> {
|
||||
val firLoop = expression.getOrBuildFirSafe<FirWhileLoop>(state) ?: return emptyList()
|
||||
val condition = firLoop.condition as? FirFunctionCall
|
||||
val iterator = run {
|
||||
val callee = (condition?.explicitReceiver as? FirQualifiedAccessExpression)?.calleeReference
|
||||
(callee?.getResolvedSymbolOfNameReference()?.fir as? FirProperty)?.getInitializerFunctionCall()
|
||||
}
|
||||
val hasNext = condition?.calleeReference?.getResolvedSymbolOfNameReference()
|
||||
val next = (firLoop.block.statements.firstOrNull() as? FirProperty?)?.getInitializerFunctionCall()
|
||||
return listOfNotNull(
|
||||
iterator?.fir?.findPsi(session),
|
||||
hasNext?.fir?.findPsi(session),
|
||||
next?.fir?.findPsi(session),
|
||||
)
|
||||
}
|
||||
|
||||
private fun FirProperty.getInitializerFunctionCall() =
|
||||
(initializer as? FirFunctionCall)?.calleeReference?.getResolvedSymbolOfNameReference()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.idea.fir.FirModuleResolveState
|
||||
import org.jetbrains.kotlin.idea.frontend.api.VariableAsFunctionLikeCallInfo
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
|
||||
class KtInvokeFunctionReferenceFirImpl(expression: KtCallExpression) : KtInvokeFunctionReference(expression), FirKtReference {
|
||||
override fun doRenameImplicitConventionalCall(newName: String?): KtExpression {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun getResolvedToPsi(
|
||||
analysisSession: AnalysisSessionFirImpl,
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState
|
||||
): Collection<PsiElement> {
|
||||
val call = analysisSession.resolveCall(expression) ?: return emptyList()
|
||||
if (call is VariableAsFunctionLikeCallInfo) {
|
||||
return listOf(call.invokeFunction)
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.references
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirStatement
|
||||
import org.jetbrains.kotlin.idea.fir.*
|
||||
import org.jetbrains.kotlin.idea.frontend.api.fir.AnalysisSessionFirImpl
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtPropertyDelegate
|
||||
|
||||
class KtPropertyDelegationMethodsReferenceFirImpl(
|
||||
element: KtPropertyDelegate
|
||||
) : KtPropertyDelegationMethodsReference(element), FirKtReference {
|
||||
override fun getResolvedToPsi(
|
||||
analysisSession: AnalysisSessionFirImpl,
|
||||
session: FirSession,
|
||||
state: FirModuleResolveState
|
||||
): Collection<PsiElement> {
|
||||
val property = (expression.parent as? KtElement)?.getOrBuildFirSafe<FirProperty>(state) ?: return emptyList()
|
||||
if (property.delegate == null) return emptyList()
|
||||
val getValueSymbol = (property.getter?.singleStatementOfType<FirReturnExpression>()?.result as? FirFunctionCall)?.getCalleeSymbol()
|
||||
val setValueSymbol = property.setter?.singleStatementOfType<FirFunctionCall>()?.getCalleeSymbol()
|
||||
return listOfNotNull(
|
||||
getValueSymbol?.fir?.findPsi(session),
|
||||
setValueSymbol?.fir?.findPsi(session)
|
||||
)
|
||||
}
|
||||
|
||||
private inline fun <reified S : FirStatement> FirPropertyAccessor.singleStatementOfType(): S? =
|
||||
body?.statements?.singleOrNull() as? S
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fun kotlin.String.fromString(what: kotlin.Int, oops: kotlin.collections.Map<MyType<kotlin.Boolean>, kotlin.collections.MutableList<kotlin.Boolean>>): kotlin.Unit {}
|
||||
|
||||
fun <T : kotlin.Number >kotlin.String.foo(what: kotlin.Int): kotlin.String { TODO() }
|
||||
|
||||
fun <T> kotlin.String.withWhere(what: kotlin.Int): T where T : kotlin.Number, T: kotlin.Comparable<kotlin.Number> { TODO() }
|
||||
|
||||
class MyType<in F>
|
||||
@@ -0,0 +1 @@
|
||||
fun ((kotlin.String) -> kotlin.Int?).foo(other: kotlin.String.() -> kotlin.Unit?): kotlin.Function2<kotlin.Int, kotlin.String, kotlin.Unit> { TODO() }
|
||||
11
idea/idea-frontend-fir/testData/ktDeclarationAndFirDeclarationEqualityChecker/inClass.kt
vendored
Normal file
11
idea/idea-frontend-fir/testData/ktDeclarationAndFirDeclarationEqualityChecker/inClass.kt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
class A<S> {
|
||||
fun x(a: kotlin.Int, b: kotlin.String): Unit {}
|
||||
|
||||
fun <T> x(a: kotlin.Int, b: java.lang.String): kotlin.Int { TODO() }
|
||||
|
||||
fun <T, Q> x(a: kotlin.collections.Map<T, kotlin.collections.Map<in S, out Q>>, b: kotlin.collections.List<kotlin.Byte>): kotlin.Int { TODO() }
|
||||
|
||||
fun <T, Q> kotlin.collections.List<kotlin.collections.Map<T, Q>>.x(f: MyType<S>): kotlin.Int { TODO() }
|
||||
}
|
||||
|
||||
class MyType<in F>
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.rt.execution.junit.FileComparisonFailure
|
||||
import junit.framework.Assert
|
||||
import junit.framework.ComparisonFailure
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||
import java.io.File
|
||||
|
||||
abstract class AbstractKtDeclarationAndFirDeclarationEqualityChecker : KotlinLightCodeInsightFixtureTestCase() {
|
||||
protected fun doTest(path: String) {
|
||||
val file = File(path)
|
||||
val ktFile = myFixture.configureByText(file.name, FileUtil.loadFile(file)) as KtFile
|
||||
|
||||
val resolveState = ktFile.firResolveState()
|
||||
ktFile.forEachDescendantOfType<KtFunction> { ktFunction ->
|
||||
val firFunction = ktFunction.getOrBuildFir(resolveState) as FirFunction<*>
|
||||
if (!KtDeclarationAndFirDeclarationEqualityChecker.representsTheSameDeclaration(ktFunction, firFunction)) {
|
||||
throw FileComparisonFailure(
|
||||
/* message= */ null,
|
||||
KtDeclarationAndFirDeclarationEqualityChecker.renderPsi(ktFunction, firFunction.session),
|
||||
KtDeclarationAndFirDeclarationEqualityChecker.renderFir(firFunction),
|
||||
/* expectedFilePath= */ null
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.fir;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/idea-frontend-fir/testData/ktDeclarationAndFirDeclarationEqualityChecker")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class KtDeclarationAndFirDeclarationEqualityCheckerGenerated extends AbstractKtDeclarationAndFirDeclarationEqualityChecker {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInKtDeclarationAndFirDeclarationEqualityChecker() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/idea-frontend-fir/testData/ktDeclarationAndFirDeclarationEqualityChecker"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionMethods.kt")
|
||||
public void testExtensionMethods() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/testData/ktDeclarationAndFirDeclarationEqualityChecker/extensionMethods.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionalTypes.kt")
|
||||
public void testFunctionalTypes() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/testData/ktDeclarationAndFirDeclarationEqualityChecker/functionalTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inClass.kt")
|
||||
public void testInClass() throws Exception {
|
||||
runTest("idea/idea-frontend-fir/testData/ktDeclarationAndFirDeclarationEqualityChecker/inClass.kt");
|
||||
}
|
||||
}
|
||||
41
idea/idea-frontend-independent/build.gradle.kts
Normal file
41
idea/idea-frontend-independent/build.gradle.kts
Normal file
@@ -0,0 +1,41 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/*
|
||||
This module should not depend on compiler specific functionality
|
||||
No dependencies on descriptors (for now we still have transitive one by psi module), fir and similar modules,
|
||||
but may be dependencies on frontend independent one like psi & type-system
|
||||
This module is needed for smooth migration from descriptor frontend based IJ plugin to interlayer based one
|
||||
*/
|
||||
|
||||
compileOnly(project(":compiler:frontend")) // we need caches form here to work with ModuleInfo :(
|
||||
compileOnly(project(":idea:idea-jps-common"))
|
||||
|
||||
compileOnly(project(":compiler:psi"))
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
compileOnly(intellijCoreDep())
|
||||
compileOnly(intellijDep())
|
||||
|
||||
Platform[191].orLower {
|
||||
compileOnly(intellijDep()) { includeJars("java-api", "java-impl") }
|
||||
}
|
||||
|
||||
Platform[192].orHigher {
|
||||
compileOnly(intellijPluginDep("java")) { includeJars("java-api", "java-impl") }
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { projectDefault() }
|
||||
}
|
||||
|
||||
testsJar()
|
||||
|
||||
projectTest {
|
||||
dependsOn(":dist")
|
||||
workingDir = rootDir
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.caches.project
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||
import com.intellij.openapi.util.UserDataHolder
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
|
||||
fun <T> Module.cacheByClass(classForKey: Class<*>, vararg dependencies: Any, provider: () -> T): T {
|
||||
return CachedValuesManager.getManager(project).cache(this, dependencies, classForKey, provider)
|
||||
}
|
||||
|
||||
fun <T> Module.cacheByClassInvalidatingOnRootModifications(classForKey: Class<*>, provider: () -> T): T {
|
||||
return cacheByClass(classForKey, ProjectRootModificationTracker.getInstance(project), provider = provider)
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that it uses lambda's class for caching (essentially, anonymous class), which means that all invocations will be cached
|
||||
* by the one and the same key.
|
||||
* It is encouraged to use explicit class, just for the sake of readability.
|
||||
*/
|
||||
fun <T> Module.cacheInvalidatingOnRootModifications(provider: () -> T): T {
|
||||
return cacheByClassInvalidatingOnRootModifications(provider::class.java, provider)
|
||||
}
|
||||
|
||||
fun <T> Project.cacheByClass(classForKey: Class<*>, vararg dependencies: Any, provider: () -> T): T {
|
||||
return CachedValuesManager.getManager(this).cache(this, dependencies, classForKey, provider)
|
||||
}
|
||||
|
||||
fun <T> Project.cacheByClassInvalidatingOnRootModifications(classForKey: Class<*>, provider: () -> T): T {
|
||||
return cacheByClass(classForKey, ProjectRootModificationTracker.getInstance(this), provider = provider)
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that it uses lambda's class for caching (essentially, anonymous class), which means that all invocations will be cached
|
||||
* by the one and the same key.
|
||||
* It is encouraged to use explicit class, just for the sake of readability.
|
||||
*/
|
||||
fun <T> Project.cacheInvalidatingOnRootModifications(provider: () -> T): T {
|
||||
return cacheByClassInvalidatingOnRootModifications(provider::class.java, provider)
|
||||
}
|
||||
|
||||
private fun <T> CachedValuesManager.cache(
|
||||
holder: UserDataHolder,
|
||||
dependencies: Array<out Any>,
|
||||
classForKey: Class<*>,
|
||||
provider: () -> T
|
||||
): T {
|
||||
return getCachedValue(
|
||||
holder,
|
||||
getKeyForClass(classForKey),
|
||||
{ CachedValueProvider.Result.create(provider(), dependencies) },
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -11,9 +11,7 @@ import com.intellij.psi.util.PsiModificationTracker
|
||||
import org.jetbrains.kotlin.analyzer.KotlinModificationTrackerService
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
class KotlinIDEModificationTrackerService(project: Project) :
|
||||
KotlinModificationTrackerService() {
|
||||
|
||||
class KotlinIDEModificationTrackerService(project: Project) : KotlinModificationTrackerService() {
|
||||
override val modificationTracker: ModificationTracker = PsiModificationTracker.SERVICE.getInstance(project)
|
||||
|
||||
override val outOfBlockModificationTracker: ModificationTracker =
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.core
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.psi.KtParenthesizedExpression
|
||||
import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
|
||||
inline fun <reified T : PsiElement> PsiElement.replaced(newElement: T): T {
|
||||
val result = replace(newElement)
|
||||
return result as? T ?: (result as KtParenthesizedExpression).expression as T
|
||||
}
|
||||
|
||||
//todo make inline
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T : PsiElement> T.copied(): T = copy() as T
|
||||
|
||||
fun String.unquote(): String = KtPsiUtil.unquoteIdentifier(this)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.idea.highlighter
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightRangeExtension
|
||||
import com.intellij.lang.annotation.AnnotationHolder
|
||||
import com.intellij.lang.annotation.Annotator
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
|
||||
abstract class AbstractKotlinPsiChecker : Annotator, HighlightRangeExtension {
|
||||
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
|
||||
val file = element.containingFile as? KtFile ?: return
|
||||
|
||||
if (!shouldHighlight(file)) return
|
||||
annotateElement(element, file, holder)
|
||||
}
|
||||
|
||||
override fun isForceHighlightParents(file: PsiFile): Boolean {
|
||||
return file is KtFile
|
||||
}
|
||||
|
||||
protected abstract fun shouldHighlight(file: KtFile): Boolean
|
||||
protected abstract fun annotateElement(element: PsiElement, containingFile: KtFile, holder: AnnotationHolder)
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
|
||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
import org.jetbrains.kotlin.psi.KtExpressionWithLabel
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.KtValueArgument
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
|
||||
@@ -73,7 +70,7 @@ internal class BeforeResolveHighlightingVisitor(holder: AnnotationHolder) : High
|
||||
val argumentName = argument.getArgumentName() ?: return
|
||||
val eq = argument.equalsToken ?: return
|
||||
createInfoAnnotation(TextRange(argumentName.startOffset, eq.endOffset), null).textAttributes =
|
||||
if(argument.parent.parent is KtAnnotationEntry)
|
||||
if (argument.parent.parent is KtAnnotationEntry)
|
||||
KotlinHighlightingColors.ANNOTATION_ATTRIBUTE_NAME_ATTRIBUTES
|
||||
else
|
||||
KotlinHighlightingColors.NAMED_ARGUMENT
|
||||
@@ -85,4 +82,24 @@ internal class BeforeResolveHighlightingVisitor(holder: AnnotationHolder) : High
|
||||
highlightName(targetLabel, KotlinHighlightingColors.LABEL)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitSuperTypeCallEntry(call: KtSuperTypeCallEntry) {
|
||||
val calleeExpression = call.calleeExpression
|
||||
val typeElement = calleeExpression.typeReference?.typeElement
|
||||
if (typeElement is KtUserType) {
|
||||
typeElement.referenceExpression?.let { highlightName(it, KotlinHighlightingColors.CONSTRUCTOR_CALL) }
|
||||
}
|
||||
super.visitSuperTypeCallEntry(call)
|
||||
}
|
||||
|
||||
|
||||
override fun visitTypeParameter(parameter: KtTypeParameter) {
|
||||
parameter.nameIdentifier?.let { highlightName(it, KotlinHighlightingColors.TYPE_PARAMETER) }
|
||||
super.visitTypeParameter(parameter)
|
||||
}
|
||||
|
||||
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||
highlightNamedDeclaration(function, KotlinHighlightingColors.FUNCTION_DECLARATION)
|
||||
super.visitNamedFunction(function)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user