FIR IDE: Begin implementing semantic highlighting via FIR
* Introduce frontend api module & implement api for FIR * Implement some basic declaration highlighting for FIR
This commit is contained in:
@@ -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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -923,9 +923,13 @@ fun main(args: Array<String>) {
|
|||||||
model("fir/multiModule", recursive = false, extension = null)
|
model("fir/multiModule", recursive = false, extension = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractFirLazyResolveTest> {
|
testClass<AbstractFirHighlightingTest> {
|
||||||
model("fir/lazyResolve", extension = "test", singleClass = true, filenameStartsLowerCase = true)
|
model("highlighter")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractFirLazyResolveTest> {
|
||||||
|
model("fir/lazyResolve", extension = "test", singleClass = true, filenameStartsLowerCase = true)
|
||||||
|
}
|
||||||
|
|
||||||
testClass<AbstractFirReferenceResolveTest> {
|
testClass<AbstractFirReferenceResolveTest> {
|
||||||
model("resolve/references", pattern = KT_WITHOUT_DOTS_IN_NAME)
|
model("resolve/references", pattern = KT_WITHOUT_DOTS_IN_NAME)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ dependencies {
|
|||||||
testRuntime(intellijPluginDep("java"))
|
testRuntime(intellijPluginDep("java"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testCompile(projectTests(":idea:idea-test-framework"))
|
||||||
testRuntime(intellijRuntimeAnnotations())
|
testRuntime(intellijRuntimeAnnotations())
|
||||||
testRuntime(project(":plugins:kapt3-idea")) { isTransitive = false }
|
testRuntime(project(":plugins:kapt3-idea")) { isTransitive = false }
|
||||||
testRuntime(project(":kotlin-reflect"))
|
testRuntime(project(":kotlin-reflect"))
|
||||||
@@ -48,7 +49,6 @@ dependencies {
|
|||||||
testRuntime(project(":idea:idea-android")) { isTransitive = false }
|
testRuntime(project(":idea:idea-android")) { isTransitive = false }
|
||||||
testRuntime(project(":plugins:lint")) { isTransitive = false }
|
testRuntime(project(":plugins:lint")) { isTransitive = false }
|
||||||
testRuntime(project(":plugins:uast-kotlin"))
|
testRuntime(project(":plugins:uast-kotlin"))
|
||||||
testRuntime(project(":nj2k:nj2k-services")) { isTransitive = false }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|||||||
+20
@@ -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.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 checkHighlighting(fileText: String) {
|
||||||
|
val checkInfos = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_INFOS_PREFIX);
|
||||||
|
|
||||||
|
// warnings are not supported yet
|
||||||
|
myFixture.checkHighlighting(/* checkWarnings= */ false, checkInfos, /* checkWeakWarnings= */ false)
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+253
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
|
|
||||||
+31
@@ -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?
|
||||||
|
}
|
||||||
+14
@@ -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
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ plugins {
|
|||||||
dependencies {
|
dependencies {
|
||||||
compileOnly(project(":compiler:psi"))
|
compileOnly(project(":compiler:psi"))
|
||||||
compileOnly(project(":idea:idea-frontend-independent"))
|
compileOnly(project(":idea:idea-frontend-independent"))
|
||||||
|
implementation(project(":idea:idea-frontend-api"))
|
||||||
compileOnly(project(":idea:idea-core"))
|
compileOnly(project(":idea:idea-core"))
|
||||||
compileOnly(project(":compiler:fir:fir2ir"))
|
compileOnly(project(":compiler:fir:fir2ir"))
|
||||||
compileOnly(project(":compiler:fir:resolve"))
|
compileOnly(project(":compiler:fir:resolve"))
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* 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.FirResolvedNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
|
|
||||||
|
fun FirFunctionCall.isImplicitFunctionCall(): Boolean {
|
||||||
|
if (dispatchReceiver !is FirQualifiedAccessExpression) return false
|
||||||
|
val resolvedCalleeSymbol = (calleeReference as? FirResolvedNamedReference)?.resolvedSymbol
|
||||||
|
return (resolvedCalleeSymbol as? FirNamedFunctionSymbol)?.fir?.name?.asString() == "invoke"
|
||||||
|
}
|
||||||
+154
@@ -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,59 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.intellij.psi.impl.source.PsiFieldImpl
|
||||||
|
import com.intellij.psi.util.elementType
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
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 && declaration.isExtensionDeclaration() -> Colors.EXTENSION_PROPERTY
|
||||||
|
declaration is KtProperty && declaration.isLocal || declaration is PsiLocalVariable ->
|
||||||
|
Colors.LOCAL_VARIABLE
|
||||||
|
declaration is KtParameter -> {
|
||||||
|
if (declaration.valOrVarKeyword != null) Colors.INSTANCE_PROPERTY
|
||||||
|
else Colors.PARAMETER
|
||||||
|
}
|
||||||
|
declaration is PsiParameter -> Colors.PARAMETER
|
||||||
|
declaration is KtProperty && declaration.isTopLevel -> {
|
||||||
|
if (declaration.isCustomPropertyDeclaration()) Colors.PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
|
||||||
|
else Colors.PACKAGE_PROPERTY
|
||||||
|
}
|
||||||
|
declaration is KtProperty -> {
|
||||||
|
if (declaration.isCustomPropertyDeclaration()) Colors.INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
|
||||||
|
else Colors.INSTANCE_PROPERTY
|
||||||
|
}
|
||||||
|
declaration is PsiField -> Colors.INSTANCE_PROPERTY
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
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 && declaration.isInterface()
|
||||||
|
|| declaration is PsiClass && declaration.isInterface && !declaration.isAnnotationType -> Colors.TRAIT
|
||||||
|
declaration.isAnnotationClass() -> Colors.ANNOTATION
|
||||||
|
declaration is KtObjectDeclaration -> Colors.OBJECT
|
||||||
|
declaration is KtEnumEntry || declaration is PsiEnumConstant -> Colors.ENUM_ENTRY
|
||||||
|
declaration is KtClass && declaration.isAbstract()
|
||||||
|
|| declaration is PsiClass && declaration.hasModifier(JvmModifier.ABSTRACT) -> Colors.ABSTRACT_CLASS
|
||||||
|
declaration is KtClass || declaration is PsiClass -> Colors.CLASS
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun PsiElement.isAnnotationClass() =
|
||||||
|
this is KtClass && isAnnotation() || this is PsiClass && isAnnotationType
|
||||||
+15
-5
@@ -8,8 +8,9 @@ package org.jetbrains.kotlin.idea.highlighter
|
|||||||
import com.intellij.lang.annotation.AnnotationHolder
|
import com.intellij.lang.annotation.AnnotationHolder
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||||
import org.jetbrains.kotlin.idea.fir.firResolveState
|
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
|
||||||
import org.jetbrains.kotlin.idea.fir.getOrBuildFirWithDiagnostics
|
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.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
@@ -20,12 +21,21 @@ class KotlinFirPsiChecker : AbstractKotlinPsiChecker() {
|
|||||||
|
|
||||||
override fun annotateElement(element: PsiElement, containingFile: KtFile, holder: AnnotationHolder) {
|
override fun annotateElement(element: PsiElement, containingFile: KtFile, holder: AnnotationHolder) {
|
||||||
if (element !is KtElement) return
|
if (element !is KtElement) return
|
||||||
val state = containingFile.firResolveState()
|
val analysisSession = AnalysisSessionFirImpl.forElement(element)
|
||||||
containingFile.getOrBuildFirWithDiagnostics(state)
|
|
||||||
|
|
||||||
val diagnostics = state.getDiagnostics(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.isEmpty()) return
|
||||||
|
|
||||||
|
if (diagnostics.none(Diagnostic::isValid)) return
|
||||||
|
|
||||||
if (shouldHighlightErrors(element)) {
|
if (shouldHighlightErrors(element)) {
|
||||||
highlightDiagnostics(diagnostics, holder)
|
highlightDiagnostics(diagnostics, holder)
|
||||||
}
|
}
|
||||||
|
|||||||
+62
@@ -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.idea.highlighter.visitors
|
||||||
|
|
||||||
|
import com.intellij.lang.annotation.AnnotationHolder
|
||||||
|
import com.intellij.psi.util.elementType
|
||||||
|
import org.jetbrains.kotlin.idea.frontend.api.FrontendAnalysisSession
|
||||||
|
import org.jetbrains.kotlin.idea.highlighter.textAttributesKeyForPropertyDeclaration
|
||||||
|
import org.jetbrains.kotlin.idea.highlighter.textAttributesKeyForTypeDeclaration
|
||||||
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.idea.highlighter.KotlinHighlightingColors as Colors
|
||||||
|
|
||||||
|
internal class DeclarationHighlightingVisitor(
|
||||||
|
analysisSession: FrontendAnalysisSession,
|
||||||
|
holder: AnnotationHolder
|
||||||
|
) : FirAfterResolveHighlightingVisitor(analysisSession, holder) {
|
||||||
|
override fun visitNamedFunction(function: KtNamedFunction) {
|
||||||
|
highlightNamedDeclaration(function, Colors.FUNCTION_DECLARATION)
|
||||||
|
super.visitNamedFunction(function)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
|
||||||
|
highlightNamedDeclaration(typeAlias, Colors.TYPE_ALIAS)
|
||||||
|
super.visitTypeAlias(typeAlias)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
|
||||||
|
textAttributesKeyForTypeDeclaration(classOrObject)?.let { attributes -> highlightNamedDeclaration(classOrObject, attributes) }
|
||||||
|
super.visitClassOrObject(classOrObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTypeParameter(parameter: KtTypeParameter) {
|
||||||
|
highlightNamedDeclaration(parameter, Colors.TYPE_PARAMETER)
|
||||||
|
super.visitTypeParameter(parameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitNamedDeclaration(declaration: KtNamedDeclaration) {
|
||||||
|
if (declaration is KtValVarKeywordOwner) {
|
||||||
|
textAttributesKeyForPropertyDeclaration(declaration)?.let { attributes ->
|
||||||
|
highlightNamedDeclaration(declaration, attributes)
|
||||||
|
}
|
||||||
|
if (declaration.valOrVarKeyword?.elementType == KtTokens.VAR_KEYWORD) {
|
||||||
|
highlightNamedDeclaration(declaration, Colors.MUTABLE_VARIABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.visitNamedDeclaration(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
override fun visitSuperTypeCallEntry(call: KtSuperTypeCallEntry) {
|
||||||
|
val calleeExpression = call.calleeExpression
|
||||||
|
val typeElement = calleeExpression.typeReference?.typeElement
|
||||||
|
if (typeElement is KtUserType) {
|
||||||
|
typeElement.referenceExpression?.let { highlightName(it, Colors.CONSTRUCTOR_CALL) }
|
||||||
|
}
|
||||||
|
super.visitSuperTypeCallEntry(call)
|
||||||
|
}
|
||||||
|
}
|
||||||
+65
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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) {
|
||||||
|
|
||||||
|
protected fun highlightNamedDeclaration(declaration: KtNamedDeclaration, key: TextAttributesKey) {
|
||||||
|
declaration.nameIdentifier?.let { highlightName(it, key) }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun createListOfVisitors(
|
||||||
|
analysisSession: FrontendAnalysisSession,
|
||||||
|
holder: AnnotationHolder
|
||||||
|
): List<FirAfterResolveHighlightingVisitor> = listOf(
|
||||||
|
TypeHighlightingVisitor(analysisSession, holder),
|
||||||
|
DeclarationHighlightingVisitor(analysisSession, holder),
|
||||||
|
FunctionCallHighlightingVisitor(analysisSession, holder),
|
||||||
|
ExpressionsSmartcastHighlightingVisitor(analysisSession, holder),
|
||||||
|
VariableReferenceHighlightingVisitor(analysisSession, holder),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+67
@@ -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
|
||||||
|
}
|
||||||
+79
@@ -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.PsiUtilCore
|
||||||
|
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 && PsiUtilCore.getElementType(valOrVarKeyword) == 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
|
||||||
|
}
|
||||||
+4
-2
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2020 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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -200,13 +200,15 @@ abstract class KotlinLightCodeInsightFixtureTestCase : KotlinLightCodeInsightFix
|
|||||||
InTextDirectivesUtils.isDirectiveDefined(fileText, "ENABLE_MULTIPLATFORM") ->
|
InTextDirectivesUtils.isDirectiveDefined(fileText, "ENABLE_MULTIPLATFORM") ->
|
||||||
KotlinProjectDescriptorWithFacet.KOTLIN_STABLE_WITH_MULTIPLATFORM
|
KotlinProjectDescriptorWithFacet.KOTLIN_STABLE_WITH_MULTIPLATFORM
|
||||||
|
|
||||||
else -> KotlinLightProjectDescriptor.INSTANCE
|
else -> getDefaultProjectDescriptor()
|
||||||
}
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
throw rethrow(e)
|
throw rethrow(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun getDefaultProjectDescriptor(): KotlinLightProjectDescriptor = KotlinLightProjectDescriptor.INSTANCE
|
||||||
|
|
||||||
protected fun isAllFilesPresentInTest(): Boolean = KotlinTestUtils.isAllFilesPresentTest(getTestName(false))
|
protected fun isAllFilesPresentInTest(): Boolean = KotlinTestUtils.isAllFilesPresentTest(getTestName(false))
|
||||||
|
|
||||||
protected fun performNotWriteEditorAction(actionId: String): Boolean {
|
protected fun performNotWriteEditorAction(actionId: String): Boolean {
|
||||||
|
|||||||
@@ -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.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
|||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.rt.execution.junit.FileComparisonFailure;
|
import com.intellij.rt.execution.junit.FileComparisonFailure;
|
||||||
import com.intellij.testFramework.ExpectedHighlightingData;
|
import com.intellij.testFramework.ExpectedHighlightingData;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase;
|
||||||
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
|
||||||
import org.jetbrains.kotlin.test.TagsTestDataUtil;
|
import org.jetbrains.kotlin.test.TagsTestDataUtil;
|
||||||
@@ -24,18 +25,23 @@ public abstract class AbstractHighlightingTest extends KotlinLightCodeInsightFix
|
|||||||
public static final String NO_CHECK_WARNINGS_PREFIX = "// NO_CHECK_WARNINGS";
|
public static final String NO_CHECK_WARNINGS_PREFIX = "// NO_CHECK_WARNINGS";
|
||||||
public static final String EXPECTED_DUPLICATED_HIGHLIGHTING_PREFIX = "// EXPECTED_DUPLICATED_HIGHLIGHTING";
|
public static final String EXPECTED_DUPLICATED_HIGHLIGHTING_PREFIX = "// EXPECTED_DUPLICATED_HIGHLIGHTING";
|
||||||
|
|
||||||
protected void doTest(String unused) throws Exception {
|
protected void checkHighlighting(@NotNull String fileText) {
|
||||||
String fileText = FileUtil.loadFile(new File(testPath()), true);
|
|
||||||
boolean checkInfos = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_INFOS_PREFIX);
|
boolean checkInfos = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_INFOS_PREFIX);
|
||||||
boolean checkWeakWarnings = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_WEAK_WARNINGS_PREFIX);
|
boolean checkWeakWarnings = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_WEAK_WARNINGS_PREFIX);
|
||||||
boolean checkWarnings = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_WARNINGS_PREFIX);
|
boolean checkWarnings = !InTextDirectivesUtils.isDirectiveDefined(fileText, NO_CHECK_WARNINGS_PREFIX);
|
||||||
|
|
||||||
|
myFixture.checkHighlighting(checkWarnings, checkInfos, checkWeakWarnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doTest(String unused) throws Exception {
|
||||||
|
String fileText = FileUtil.loadFile(new File(testPath()), true);
|
||||||
boolean expectedDuplicatedHighlighting = InTextDirectivesUtils.isDirectiveDefined(fileText, EXPECTED_DUPLICATED_HIGHLIGHTING_PREFIX);
|
boolean expectedDuplicatedHighlighting = InTextDirectivesUtils.isDirectiveDefined(fileText, EXPECTED_DUPLICATED_HIGHLIGHTING_PREFIX);
|
||||||
|
|
||||||
myFixture.configureByFile(fileName());
|
myFixture.configureByFile(fileName());
|
||||||
|
|
||||||
withExpectedDuplicatedHighlighting(expectedDuplicatedHighlighting, () -> {
|
withExpectedDuplicatedHighlighting(expectedDuplicatedHighlighting, () -> {
|
||||||
try {
|
try {
|
||||||
myFixture.checkHighlighting(checkWarnings, checkInfos, checkWeakWarnings);
|
checkHighlighting(fileText);
|
||||||
}
|
}
|
||||||
catch (FileComparisonFailure e) {
|
catch (FileComparisonFailure e) {
|
||||||
List<HighlightInfo> highlights =
|
List<HighlightInfo> highlights =
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ val projectsToShadow by extra(listOf(
|
|||||||
":idea:idea-jps-common",
|
":idea:idea-jps-common",
|
||||||
":idea:idea-frontend-independent",
|
":idea:idea-frontend-independent",
|
||||||
":idea:idea-frontend-fir",
|
":idea:idea-frontend-fir",
|
||||||
|
":idea:idea-frontend-api",
|
||||||
*if (Ide.IJ())
|
*if (Ide.IJ())
|
||||||
arrayOf(
|
arrayOf(
|
||||||
":idea:idea-maven",
|
":idea:idea-maven",
|
||||||
|
|||||||
@@ -185,6 +185,7 @@ include ":kotlin-build-common",
|
|||||||
":idea:scripting-support",
|
":idea:scripting-support",
|
||||||
":idea:idea-frontend-independent",
|
":idea:idea-frontend-independent",
|
||||||
":idea:idea-frontend-fir",
|
":idea:idea-frontend-fir",
|
||||||
|
":idea:idea-frontend-api",
|
||||||
":libraries:tools:new-project-wizard",
|
":libraries:tools:new-project-wizard",
|
||||||
":idea:idea-new-project-wizard",
|
":idea:idea-new-project-wizard",
|
||||||
":libraries:tools:new-project-wizard:new-project-wizard-cli",
|
":libraries:tools:new-project-wizard:new-project-wizard-cli",
|
||||||
|
|||||||
Reference in New Issue
Block a user