mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
AP-8446 [devkit]: reference provider for FUS group and event IDs + missing description inspection
GitOrigin-RevId: 4f07dc713edd53dc2bc72ff291227a4853580e72
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f0269e1da8
commit
6b7ecb38dc
@@ -35,6 +35,7 @@ open class EventLogGroup {
|
||||
val groupData: List<Pair<EventField<*>, FeatureUsageData.() -> Unit>>
|
||||
|
||||
@Deprecated("Descriptions are moved to a separate file; use another constructor", ReplaceWith("EventLogGroup(id, version, recorder, groupData)"))
|
||||
@Suppress("EventLogDescription")
|
||||
constructor(
|
||||
@EventIdName id: String,
|
||||
version: Int,
|
||||
@@ -68,6 +69,7 @@ open class EventLogGroup {
|
||||
}
|
||||
|
||||
@Deprecated("Descriptions are moved to a separate file; use another constructor", ReplaceWith("EventLogGroup(id, version, recorder)"))
|
||||
@Suppress("EventLogDescription")
|
||||
constructor(
|
||||
@EventIdName id: String,
|
||||
version: Int,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports missing FUS group or event descriptions in the corresponding recorder properties files (<code>build/event/*.properties</code>),
|
||||
and warns when a group or event ID cannot be evaluated.
|
||||
</body>
|
||||
</html>
|
||||
@@ -28,6 +28,7 @@
|
||||
<gotoRelatedProvider implementation="org.jetbrains.idea.devkit.testAssistant.TestCaseAsRelatedFileProvider"/>
|
||||
<gotoRelatedProvider implementation="org.jetbrains.idea.devkit.navigation.DescriptionInspectionGotoRelatedProvider"/>
|
||||
<psi.referenceContributor language="UAST" implementation="org.jetbrains.idea.devkit.testAssistant.TestDataReferenceContributor"/>
|
||||
<psi.referenceContributor language="UAST" implementation="org.jetbrains.idea.devkit.references.EventLogDescriptionReferenceContributor"/>
|
||||
|
||||
<automaticRenamerFactory implementation="org.jetbrains.idea.devkit.refactoring.InspectionAutomaticRenamerFactory"/>
|
||||
<httpRequestHandler implementation="org.jetbrains.idea.devkit.requestHandlers.HttpDebugListener"/>
|
||||
@@ -573,6 +574,10 @@
|
||||
groupKey="inspections.group.code"
|
||||
key="inspection.use.optimized.eel.functions.display.name"/>"
|
||||
|
||||
<localInspection language="UAST" projectType="INTELLIJ_PLUGIN" enabledByDefault="true" level="WARNING" shortName="EventLogDescription"
|
||||
groupPathKey="inspections.group.path" groupKey="inspections.group.code" key="inspections.event.log.description.display.name"
|
||||
implementationClass="org.jetbrains.idea.devkit.inspections.EventLogDescriptionInspection"/>
|
||||
|
||||
<moduleConfigurationEditorProvider implementation="org.jetbrains.idea.devkit.module.PluginModuleEditorsProvider"/>
|
||||
<implicitUsageProvider implementation="org.jetbrains.idea.devkit.inspections.DevKitImplicitUsageProvider"/>
|
||||
|
||||
|
||||
@@ -382,6 +382,17 @@ inspections.use.gray.awt.color.used.name='java.awt.Color' used for gray
|
||||
inspections.use.gray.fix.convert.name=Convert to ''Gray._{0}''
|
||||
inspections.use.gray.fix.convert.family.name=Convert to 'Gray'
|
||||
|
||||
inspections.event.log.description.display.name=Missing event log descriptions
|
||||
inspections.event.log.recorder.not.evaluable=Cannot evaluate the recorder name; consider using a constant expression
|
||||
inspections.event.log.recorder.unknown=Unknown recorder (''{0}'' is missing)
|
||||
inspections.event.log.group.id.not.evaluable=Cannot evaluate the group ID; consider using a constant expression
|
||||
inspections.event.log.group.description.missing=Group ''{0}'' description is missing from ''{1}''
|
||||
inspections.event.log.group.description.empty=Group ''{0}'' description is empty
|
||||
inspections.event.log.event.id.not.evaluable=Cannot evaluate the event ID; consider using a constant expression
|
||||
inspections.event.log.event.group.not.evaluable=Cannot find the event group; consider using a constant expression
|
||||
inspections.event.log.event.description.missing=Event ''{0}'' description is missing from ''{1}''
|
||||
inspections.event.log.event.description.empty=Event ''{0}'' description is empty
|
||||
|
||||
line.marker.related.property.tooltip=Related property
|
||||
line.marker.related.property.popup.title=Related Properties
|
||||
line.marker.related.property.description=Related property
|
||||
|
||||
@@ -3,15 +3,13 @@ package org.jetbrains.idea.devkit;
|
||||
|
||||
import com.intellij.DynamicBundle;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class DevKitBundle {
|
||||
|
||||
public static final @NonNls String BUNDLE = "messages.DevKitBundle";
|
||||
public static final String BUNDLE = "messages.DevKitBundle";
|
||||
|
||||
private static final DynamicBundle ourInstance = new DynamicBundle(DevKitBundle.class, BUNDLE);
|
||||
|
||||
@@ -19,8 +17,10 @@ public final class DevKitBundle {
|
||||
return ourInstance.getMessage(key, params);
|
||||
}
|
||||
|
||||
public static @NotNull Supplier<@Nls String> messagePointer(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key,
|
||||
Object @NotNull ... params) {
|
||||
public static @NotNull Supplier<@Nls String> messagePointer(
|
||||
@NotNull @PropertyKey(resourceBundle = BUNDLE) String key,
|
||||
Object @NotNull ... params
|
||||
) {
|
||||
return ourInstance.getLazyMessage(key, params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.inspections
|
||||
|
||||
import com.intellij.codeInspection.AbstractBaseUastLocalInspectionTool
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession
|
||||
import com.intellij.codeInspection.ProblemHighlightType
|
||||
import com.intellij.codeInspection.ProblemsHolder
|
||||
import com.intellij.lang.properties.PropertiesFileType
|
||||
import com.intellij.openapi.project.guessProjectDir
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiElementVisitor
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.uast.UastHintedVisitorAdapter
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.PropertyKey
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
import org.jetbrains.idea.devkit.DevKitBundle
|
||||
import org.jetbrains.idea.devkit.references.EVENT_LOG_GROUP_FQN
|
||||
import org.jetbrains.idea.devkit.references.EVENT_LOG_PROPERTIES_DIR
|
||||
import org.jetbrains.idea.devkit.references.eventLogGroupCall
|
||||
import org.jetbrains.idea.devkit.references.findEventLogPropertiesFile
|
||||
import org.jetbrains.idea.devkit.references.findGroupIdAndRecorderName
|
||||
import org.jetbrains.idea.devkit.references.findRecorderName
|
||||
import org.jetbrains.uast.UCallExpression
|
||||
import org.jetbrains.uast.UElement
|
||||
import org.jetbrains.uast.UastCallKind
|
||||
import org.jetbrains.uast.evaluateString
|
||||
import org.jetbrains.uast.visitor.AbstractUastNonRecursiveVisitor
|
||||
|
||||
@VisibleForTesting
|
||||
@ApiStatus.Internal
|
||||
class EventLogDescriptionInspection : AbstractBaseUastLocalInspectionTool() {
|
||||
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor {
|
||||
val hasFUS = JavaPsiFacade.getInstance(holder.project).findClass(EVENT_LOG_GROUP_FQN, holder.file.resolveScope) != null
|
||||
if (!hasFUS)
|
||||
return PsiElementVisitor.EMPTY_VISITOR
|
||||
|
||||
val hasDescriptions = holder.project.guessProjectDir()
|
||||
?.findFileByRelativePath(EVENT_LOG_PROPERTIES_DIR)
|
||||
?.let { PsiManager.getInstance(holder.project).findDirectory(it) }
|
||||
?.let { it.files.any { file -> file.name.endsWith(PropertiesFileType.DOT_DEFAULT_EXTENSION) } } == true
|
||||
if (!hasDescriptions)
|
||||
return PsiElementVisitor.EMPTY_VISITOR
|
||||
|
||||
return UastHintedVisitorAdapter.create(
|
||||
holder.file.language,
|
||||
EventLogDescriptionInspectionVisitor(holder),
|
||||
arrayOf(UCallExpression::class.java),
|
||||
directOnly = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private val EVENT_LOG_GROUP_CALL_PATTERN = eventLogGroupCall()
|
||||
|
||||
private class EventLogDescriptionInspectionVisitor(private val holder: ProblemsHolder) : AbstractUastNonRecursiveVisitor() {
|
||||
override fun visitCallExpression(node: UCallExpression): Boolean {
|
||||
val argument = node.getArgumentForParameter(0)
|
||||
if (argument != null && EVENT_LOG_GROUP_CALL_PATTERN.accepts(node)) {
|
||||
if (node.kind == UastCallKind.CONSTRUCTOR_CALL) {
|
||||
val recorderArg = node.getArgumentForParameter(2)
|
||||
val recorder = findRecorderName(node)
|
||||
?: return warn(recorderArg ?: node, "inspections.event.log.recorder.not.evaluable")
|
||||
val file = findEventLogPropertiesFile(holder.project, recorder)
|
||||
?: return error(recorderArg ?: node, "inspections.event.log.recorder.unknown", "${EVENT_LOG_PROPERTIES_DIR}/${recorder}.properties")
|
||||
val groupId = argument.evaluateString()?.takeIf { it.isNotBlank() }
|
||||
?: return warn(argument, "inspections.event.log.group.id.not.evaluable")
|
||||
val description = file.findPropertyByKey(groupId)?.value
|
||||
?: return error(argument, "inspections.event.log.group.description.missing", groupId, file.name)
|
||||
if (description.isBlank())
|
||||
error(argument, "inspections.event.log.group.description.empty", groupId)
|
||||
}
|
||||
else {
|
||||
val receiver = node.receiver
|
||||
val (groupId, recorder) = receiver?.let { findGroupIdAndRecorderName(it) }
|
||||
?: return warn(receiver ?: node, "inspections.event.log.event.group.not.evaluable")
|
||||
val eventId = argument.evaluateString()?.takeIf { it.isNotBlank() }
|
||||
?: return warn(argument, "inspections.event.log.event.id.not.evaluable")
|
||||
findEventLogPropertiesFile(holder.project, recorder)?.let { file ->
|
||||
val key = "${groupId}.${eventId}"
|
||||
val description = file.findPropertyByKey(key)?.value
|
||||
?: return error(argument, "inspections.event.log.event.description.missing", key, file.name)
|
||||
if (description.isBlank())
|
||||
error(argument, "inspections.event.log.event.description.empty", key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun warn(element: UElement, messageKey: @PropertyKey(resourceBundle = DevKitBundle.BUNDLE) String): Boolean {
|
||||
element.sourcePsi?.let {
|
||||
holder.registerProblem(it, DevKitBundle.message(messageKey), ProblemHighlightType.WARNING)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun error(element: UElement, messageKey: @PropertyKey(resourceBundle = DevKitBundle.BUNDLE) String, vararg params: Any): Boolean {
|
||||
element.sourcePsi?.let {
|
||||
holder.registerProblem(it, DevKitBundle.message(messageKey, *params), ProblemHighlightType.GENERIC_ERROR)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.references
|
||||
|
||||
import com.intellij.lang.properties.psi.PropertiesFile
|
||||
import com.intellij.lang.properties.references.PropertyReferenceBase
|
||||
import com.intellij.patterns.uast.injectionHostUExpression
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiLanguageInjectionHost
|
||||
import com.intellij.psi.PsiReference
|
||||
import com.intellij.psi.PsiReferenceContributor
|
||||
import com.intellij.psi.PsiReferenceRegistrar
|
||||
import com.intellij.psi.UastInjectionHostReferenceProvider
|
||||
import com.intellij.psi.registerUastReferenceProvider
|
||||
import com.intellij.util.ProcessingContext
|
||||
import org.jetbrains.uast.UCallExpression
|
||||
import org.jetbrains.uast.UExpression
|
||||
import org.jetbrains.uast.UastCallKind
|
||||
import org.jetbrains.uast.evaluateString
|
||||
import org.jetbrains.uast.getParentOfType
|
||||
|
||||
internal class EventLogDescriptionReferenceContributor : PsiReferenceContributor() {
|
||||
override fun registerReferenceProviders(registrar: PsiReferenceRegistrar) {
|
||||
registrar.registerUastReferenceProvider(
|
||||
injectionHostUExpression().callParameter(0, eventLogGroupCall()),
|
||||
EventLogDescriptionReferenceProvider(),
|
||||
PsiReferenceRegistrar.DEFAULT_PRIORITY,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class EventLogDescriptionReferenceProvider : UastInjectionHostReferenceProvider() {
|
||||
override fun getReferencesForInjectionHost(
|
||||
uExpression: UExpression,
|
||||
host: PsiLanguageInjectionHost,
|
||||
context: ProcessingContext,
|
||||
): Array<PsiReference> {
|
||||
val call = uExpression.getParentOfType(UCallExpression::class.java, true) ?: return PsiReference.EMPTY_ARRAY
|
||||
if (call.kind == UastCallKind.CONSTRUCTOR_CALL) {
|
||||
val groupId = uExpression.evaluateString() ?: return PsiReference.EMPTY_ARRAY
|
||||
val recorder = findRecorderName(call) ?: return PsiReference.EMPTY_ARRAY
|
||||
return arrayOf(EventLogDescriptionReference(groupId, host, recorder))
|
||||
}
|
||||
else {
|
||||
val eventId = uExpression.evaluateString() ?: return PsiReference.EMPTY_ARRAY
|
||||
val receiver = call.receiver ?: return PsiReference.EMPTY_ARRAY
|
||||
val (groupId, recorder) = findGroupIdAndRecorderName(receiver) ?: return PsiReference.EMPTY_ARRAY
|
||||
return arrayOf(EventLogDescriptionReference("${groupId}.${eventId}", host, recorder))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class EventLogDescriptionReference(key: String, element: PsiElement, private val recorder: String)
|
||||
: PropertyReferenceBase(key, /*soft =*/ true, element)
|
||||
{
|
||||
override fun getPropertiesFiles(): List<PropertiesFile?> {
|
||||
val file = findEventLogPropertiesFile(this.element.project, recorder)
|
||||
return if (file != null) listOf(file) else emptyList()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.references
|
||||
|
||||
import com.intellij.internal.statistic.eventLog.FUS_RECORDER
|
||||
import com.intellij.lang.properties.psi.PropertiesFile
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.guessProjectDir
|
||||
import com.intellij.patterns.ElementPattern
|
||||
import com.intellij.patterns.PsiJavaPatterns.psiMethod
|
||||
import com.intellij.patterns.uast.callExpression
|
||||
import com.intellij.psi.PsiManager
|
||||
import org.jetbrains.uast.UCallExpression
|
||||
import org.jetbrains.uast.UExpression
|
||||
import org.jetbrains.uast.UMethod
|
||||
import org.jetbrains.uast.UQualifiedReferenceExpression
|
||||
import org.jetbrains.uast.UResolvable
|
||||
import org.jetbrains.uast.UVariable
|
||||
import org.jetbrains.uast.UastCallKind
|
||||
import org.jetbrains.uast.evaluateString
|
||||
import org.jetbrains.uast.resolveToUElement
|
||||
import org.jetbrains.uast.toUElementOfType
|
||||
|
||||
internal const val EVENT_LOG_GROUP_FQN = "com.intellij.internal.statistic.eventLog.EventLogGroup"
|
||||
internal const val EVENT_LOG_PROPERTIES_DIR = "build/events"
|
||||
|
||||
private const val REGISTER_EVENT_NAME = "registerEvent"
|
||||
private const val REGISTER_VARARG_EVENT_NAME = "registerVarargEvent"
|
||||
|
||||
internal fun eventLogGroupCall(): ElementPattern<UCallExpression> = callExpression().andOr(
|
||||
callExpression().constructor(EVENT_LOG_GROUP_FQN),
|
||||
callExpression().withAnyResolvedMethod(
|
||||
psiMethod().withName(REGISTER_EVENT_NAME, REGISTER_VARARG_EVENT_NAME).definedInClass(EVENT_LOG_GROUP_FQN)
|
||||
)
|
||||
)
|
||||
|
||||
internal fun findRecorderName(call: UCallExpression): String? {
|
||||
val recorderArg = call.getArgumentForParameter(2) ?: return FUS_RECORDER
|
||||
return recorderArg.evaluateString()?.takeIf { it.isNotBlank() }
|
||||
}
|
||||
|
||||
internal fun findGroupIdAndRecorderName(expression: UExpression): Pair<String, String>? = when (expression) {
|
||||
is UCallExpression if (expression.kind == UastCallKind.CONSTRUCTOR_CALL) -> {
|
||||
val groupId = expression.getArgumentForParameter(0)?.let(UExpression::evaluateString) ?: return null
|
||||
val recorder = findRecorderName(expression) ?: return null
|
||||
groupId to recorder
|
||||
}
|
||||
is UQualifiedReferenceExpression -> {
|
||||
findGroupIdAndRecorderName(expression.selector)
|
||||
}
|
||||
else -> {
|
||||
val variable = when (val resolved = (expression as? UResolvable)?.resolveToUElement()) {
|
||||
is UVariable -> resolved
|
||||
is UMethod -> resolved.sourcePsi.toUElementOfType<UVariable>() // Kotlin synthetic accessors
|
||||
else -> null
|
||||
} ?: return null
|
||||
val initializer = variable.uastInitializer ?: return null
|
||||
findGroupIdAndRecorderName(initializer)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun findEventLogPropertiesFile(project: Project, recorder: String): PropertiesFile? {
|
||||
val projectDir = project.guessProjectDir() ?: return null
|
||||
val file = projectDir.findFileByRelativePath("${EVENT_LOG_PROPERTIES_DIR}/${recorder}.properties") ?: return null
|
||||
return PsiManager.getInstance(project).findFile(file) as? PropertiesFile
|
||||
}
|
||||
+1
-2
@@ -12,8 +12,7 @@ import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class DevkitInspectionsRegistrationCheckTest extends BasePlatformTestCase {
|
||||
|
||||
private static final int EXPECTED_INSPECTIONS_NUMBER = 93;
|
||||
private static final int EXPECTED_INSPECTIONS_NUMBER = 94;
|
||||
|
||||
/**
|
||||
* Inspections that are finished and intentionally disabled.
|
||||
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package org.jetbrains.idea.devkit.references
|
||||
|
||||
import com.intellij.lang.properties.psi.Property
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase5
|
||||
import org.jetbrains.idea.devkit.inspections.EventLogDescriptionInspection
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNotEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.assertInstanceOf
|
||||
import org.junit.jupiter.api.assertNotNull
|
||||
|
||||
class EventLogDescriptionReferenceContributorTest : LightJavaCodeInsightFixtureTestCase5() {
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
fixture.addClass("""
|
||||
package com.intellij.internal.statistic.eventLog;
|
||||
public class EventLogGroup {
|
||||
public EventLogGroup(String id, int version) {}
|
||||
public EventLogGroup(String id, int version, String recorder) {}
|
||||
public EventId registerEvent(String id) {}
|
||||
public EventId registerVarargEvent(String id, Object... fields) {}
|
||||
public static class EventId {}
|
||||
}""".trimIndent()
|
||||
)
|
||||
fixture.addFileToProject("build/events/FUS.properties", """
|
||||
my.group=FUS group
|
||||
my.group.event=FUS event
|
||||
my.group.var.event=FUS vararg event
|
||||
empty.group=
|
||||
my.group.empty.event=
|
||||
""".trimIndent())
|
||||
fixture.addFileToProject("build/events/ML.properties", "ml.group=ML group")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `group in default recorder - Java`() {
|
||||
fixture.configureByText("Foo.java", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup;
|
||||
class Foo {
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("my.group<caret>", 1);
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
testResolve("FUS.properties", "FUS group")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `event in default recorder - Java`() {
|
||||
fixture.configureByText("Foo.java", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup;
|
||||
class Foo {
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("my.group", 1);
|
||||
private static final EventLogGroup.EventId EVENT = GROUP.registerEvent("event<caret>");
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
testResolve("FUS.properties", "FUS event")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `vararg event in default recorder - Java`() {
|
||||
fixture.configureByText("Foo.java", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup;
|
||||
class Foo {
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("my.group", 1);
|
||||
private static final EventLogGroup.EventId EVENT = GROUP.registerVarargEvent("var.event<caret>", "whatever");
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
testResolve("FUS.properties", "FUS vararg event")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `group in default recorder - Kotlin`() {
|
||||
fixture.configureByText("Foo.kt", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
object Foo {
|
||||
private val GROUP = EventLogGroup("my.group<caret>", 1)
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
testResolve("FUS.properties", "FUS group")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `event in default recorder - Kotlin`() {
|
||||
fixture.configureByText("Foo.kt", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
object Foo {
|
||||
val GROUP = EventLogGroup("my.group", 1) // public, to verify the Kotlin property accessor way
|
||||
val EVENT = GROUP.registerEvent("event<caret>")
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
testResolve("FUS.properties", "FUS event")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `vararg event in default recorder - Kotlin`() {
|
||||
fixture.configureByText("Foo.kt", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
object Foo {
|
||||
private val GROUP = EventLogGroup("my.group", 1)
|
||||
private val EVENT = GROUP.registerVarargEvent("var.event<caret>", "whatever")
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
testResolve("FUS.properties", "FUS vararg event")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `group in custom recorder`() {
|
||||
fixture.configureByText("Foo.java", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup;
|
||||
class Foo {
|
||||
private static final String RECORDER = "ML";
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("ml.group<caret>", 1, RECORDER);
|
||||
}""".trimIndent()
|
||||
)
|
||||
testResolve("ML.properties", "ML group")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `skipping navigation when recorder is non-evaluatable`() {
|
||||
fixture.configureByText("Foo.java", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup;
|
||||
class Foo {
|
||||
private static String recorder() { return "ML"; }
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("ml.group<caret>", 1, recorder());
|
||||
}""".trimIndent()
|
||||
)
|
||||
|
||||
testNoResolve()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `problem highlighting - Java`() {
|
||||
fixture.enableInspections(EventLogDescriptionInspection::class.java)
|
||||
fixture.configureByText("Foo.java", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup;
|
||||
class Foo {
|
||||
// the good
|
||||
private static final EventLogGroup GROUP = new EventLogGroup("my.group", 1);
|
||||
private static final EventLogGroup.EventId EVENT = GROUP.registerEvent("event");
|
||||
// the bad
|
||||
private static final EventLogGroup G1 =
|
||||
new EventLogGroup("-", 1, <warning descr="Cannot evaluate the recorder name; consider using a constant expression">System.getProperty("recorder")</warning>);
|
||||
private static final EventLogGroup G2 =
|
||||
new EventLogGroup("-", 1, <error descr="Unknown recorder ('build/events/WTF.properties' is missing)">"WTF"</error>);
|
||||
private static final EventLogGroup G3 =
|
||||
new EventLogGroup(<warning descr="Cannot evaluate the group ID; consider using a constant expression">System.getProperty("group")</warning>, 1, "FUS");
|
||||
private static final EventLogGroup G4 =
|
||||
new EventLogGroup(<error descr="Group 'missing.group' description is missing from 'FUS.properties'">"missing.group"</error>, 1);
|
||||
private static final EventLogGroup G5 =
|
||||
new EventLogGroup(<error descr="Group 'empty.group' description is empty">"empty.group"</error>, 1);
|
||||
// the ugly
|
||||
private static EventLogGroup group() { return new EventLogGroup("my.group", 1); }
|
||||
private static final EventLogGroup.EventId E1 =
|
||||
<warning descr="Cannot find the event group; consider using a constant expression">group()</warning>.registerEvent("-");
|
||||
private static final EventLogGroup.EventId E2 =
|
||||
GROUP.registerEvent(<warning descr="Cannot evaluate the event ID; consider using a constant expression">System.getProperty("event")</warning>);
|
||||
private static final EventLogGroup.EventId E3 =
|
||||
GROUP.registerEvent(<error descr="Event 'my.group.missing.event' description is missing from 'FUS.properties'">"missing.event"</error>);
|
||||
private static final EventLogGroup.EventId E4 =
|
||||
GROUP.registerEvent(<error descr="Event 'my.group.empty.event' description is empty">"empty.event"</error>);
|
||||
}""".trimIndent()
|
||||
)
|
||||
fixture.checkHighlighting()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `problem highlighting - Kotlin`() {
|
||||
fixture.enableInspections(EventLogDescriptionInspection::class.java)
|
||||
fixture.configureByText("Foo.kt", """
|
||||
import com.intellij.internal.statistic.eventLog.EventLogGroup
|
||||
object Foo {
|
||||
// the good
|
||||
private val GROUP = EventLogGroup("my.group", 1)
|
||||
private val EVENT = GROUP.registerEvent("event")
|
||||
// the bad
|
||||
private val G1 = EventLogGroup("-", 1, <warning descr="Cannot evaluate the recorder name; consider using a constant expression">System.getProperty("recorder")</warning>)
|
||||
private val G2 = EventLogGroup("-", 1, <error descr="Unknown recorder ('build/events/WTF.properties' is missing)">"WTF"</error>)
|
||||
private val G3 = EventLogGroup(<warning descr="Cannot evaluate the group ID; consider using a constant expression">System.getProperty("group")</warning>, 1, "FUS")
|
||||
private val G4 = EventLogGroup(<error descr="Group 'missing.group' description is missing from 'FUS.properties'">"missing.group"</error>, 1)
|
||||
private val G5 = EventLogGroup(<error descr="Group 'empty.group' description is empty">"empty.group"</error>, 1)
|
||||
// the ugly
|
||||
private fun group() = EventLogGroup("my.group", 1)
|
||||
private val E1 = <warning descr="Cannot find the event group; consider using a constant expression">group()</warning>.registerEvent("-")
|
||||
private val E2 = GROUP.registerEvent(<warning descr="Cannot evaluate the event ID; consider using a constant expression">System.getProperty("event")</warning>)
|
||||
private val E3 = GROUP.registerEvent(<error descr="Event 'my.group.missing.event' description is missing from 'FUS.properties'">"missing.event"</error>)
|
||||
private val E4 = GROUP.registerEvent(<error descr="Event 'my.group.empty.event' description is empty">"empty.event"</error>)
|
||||
}""".trimIndent()
|
||||
)
|
||||
fixture.checkHighlighting()
|
||||
}
|
||||
|
||||
private fun testResolve(expectedFile: String, expectedText: String) = runReadAction {
|
||||
val reference = fixture.getReferenceAtCaretPosition()
|
||||
assertNotNull(reference)
|
||||
assertEquals("EventLogDescriptionReference", reference.javaClass.simpleName)
|
||||
val property = assertInstanceOf<Property>(reference.resolve())
|
||||
assertEquals(expectedFile, property.containingFile.name)
|
||||
assertEquals(expectedText, property.value)
|
||||
}
|
||||
|
||||
private fun testNoResolve() {
|
||||
val reference = fixture.getReferenceAtCaretPosition()
|
||||
if (reference != null) {
|
||||
assertNotEquals("EventLogDescriptionReference", reference.javaClass.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user