JetBrains Platform
Plugin and extension development for JetBrains products.
Ampliar la funcionalidad de Qodana con inspecciones personalizadas de código
Qodana es una herramienta de análisis estático de código que lleva las inspecciones de código y los arreglos rápidos de los JetBrains IDEs al ámbito de la integración continua. Puede ejecutarse en la nube, ejecutarse desde un contenedor Docker, integrarse en procesos de CI/CD o invocarse a través de un JetBrains IDE.
Qodana ya ofrece un impresionante conjunto de inspecciones, pero no se limita a lo que lleva incorporado. Puede añadir inspecciones personalizadas para hacer cumplir las especificaciones y convenciones del proyecto.
Por ejemplo, imagine un proyecto con una convención de código específica:
Cada clase Kotlin de un paquete
servicedebe tener un sufijoService.
En este caso, com.jetbrains.service.JetComponent no se ajustaría a esta convención, mientras que com.jetbrains.service.BrainComponentService sería perfectamente adecuada. Para continuar, crearemos un complemento que implemente esta inspección, para que Qodana pueda hacer cumplir esta convención en futuros proyectos.
Podemos implementar esta convención de código creando una inspección de código personalizada empaquetada en un complemento. Los complementos de Qodana se desarrollan igual que los de los JetBrains IDEs, es decir, solo tenemos que crear un complemento de IntelliJ Platform que se pueda ejecutar en Qodana. He aquí un rápido resumen de los pasos que seguiremos:
- Inicialice el proyecto desde IntelliJ Platform Plugin Template.
- Ajuste las propiedades del proyecto y el descriptor del complemento junto con las dependencias necesarias.
- Declare la inspección local en el descriptor del complemento e impleméntelo en Kotlin.
- Compile y empaquete el complemento.
- En el proyecto de prueba de ejemplo, sitúe el artefacto del complemento en un directorio correcto.
- Ajuste el archivo de configuración de Qodana.
- Ejecute Qodana y mire el informe.
Preparación del proyecto del complemento
Para arrancar el proyecto, visite el repositorio IntelliJ Platform Plugin Template y haga clic en el botón Use this template para crear un repositorio de complementos. Llámelo classname-inspection-qodana-plugin, copie la URL del proyecto y ábralo en IntelliJ IDEA. Cuando el proyecto esté listo, personalice gradle.properties declarando pluginGroup, pluginName y pluginRepositoryUrl según sea necesario. No se olvide de pulsar el botón flotante Sync Gradle Changes para aplicar los cambios. Para modificar el identificador único del complemento, cambie el elemento id en el descriptor del complemento plugin.xml.
Declarar dependencias
Nuestra inspección de código tiene como objetivo las clases Kotlin, por lo que necesitamos añadir el complemento de Kotlin a las dependencias del complemento de Qodana. El archivo gradle.properties requiere que declare:
platformBundledPlugins = org.jetbrains.kotlin
Además, el descriptor del complemento plugin.xml debe contener el mismo complemento Kotlin empaquetado en sus dependencias:
org.jetbrains.kotlin
De nuevo, recuerde sincronizar los cambios de Gradle pulsando el botón flotante.
Además, la inspección de clases de Kotlin debe ser compatible con el compilador K2 de Kotlin, habilitado de forma predeterminada desde la versión 2025.1 de IntelliJ Platform. En el descriptor del complemento, declare la extensión org.jetbrains.kotlin.supportsKotlinPluginMode.
Creación de la inspección de código
El código real para cualquier inspección de código que se dirija a clases Kotlin requiere tres pasos:
- Declare una extensión
com.intellij.localInspectionen el descriptor del complemento junto con los atributos necesarios y una referencia totalmente cualificada a la clase de implementación. - Cree una clase de implementación, preferiblemente en Kotlin.
- Proporcione un archivo HTML independiente con una descripción de la inspección, directrices de uso y un ejemplo.
Declarar la extensión
Añada la siguiente declaración al archivo descriptor del complemento plugin.xml:
El atributo language indica que la inspección se aplica a los archivos de código fuente en Kotlin. Es importante activar explícitamente la inspección de forma predeterminada; de lo contrario, Qodana no la ejecutará. A continuación, proporcione un displayName descriptivo, legible para el usuario, que se mostrará en el informe y en la configuración. El atributo groupName establece la categoría de inspección que se muestra tanto en el informe de Qodana como en la configuración del IDE. Por último, proporcione un nombre completamente cualificado para la clase de implementación.
Código fuente de inspección del código
El complemento de Kotlin proporciona una clase de inspección base muy útil para las inspecciones de Kotlin: AbstractKotlinInspection. Anule el método buildVisitor y proporcione una instancia de visitante PSI que recorra los elementos de clase de Kotlin de forma segura en cuanto a tipos. classVisitor es una práctica función similar a la de DSL que devuelve este tipo de visitante PSI y se invoca sobre cualquier clase Kotlin del proyecto que esté inspeccionando.
package org.intellij.sdk.codeInspection
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.codeInspection.ProblemsHolder
import com.intellij.psi.PsiElementVisitor
import org.jetbrains.kotlin.idea.codeinsight.api.classic.inspections.AbstractKotlinInspection
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtVisitorVoid
import org.jetbrains.kotlin.psi.classVisitor
class ServicePackageClassNameInspection : AbstractKotlinInspection() {
override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean) = classVisitor { klass ->
val classNamePsi = klass.nameIdentifier ?: return@classVisitor
val classFqn = klass.fqName?.asString() ?: return@classVisitor
if (klass.packageLastComponent == "service" && !classFqn.endsWith("Service")) {
holder.registerProblem(
classNamePsi,
"Class name in the 'service' package must have a 'Service' suffix"
)
}
}
private val KtClass.packageLastComponent: String
get() = containingKtFile.packageFqName.shortName().asString()
}
La subclase del visitante extrae el nombre de clase de Kotlin totalmente cualificado, inspecciona el elemento del paquete situado más a la derecha y comprueba el sufijo correspondiente. Cualquier nombre de clase incorrecto se notifica a la instancia ProblemsHolder con una clase envolvente como elemento PSI y una descripción del problema legible para el usuario.
Descripción de la inspección
Cada inspección local requiere un archivo de descripción complementario, representado como HTML. Si utiliza el arreglo rápido Create description file ServicePackageClassNameInspection.html, se creará un archivo llamado src/main/resources/inspectionDescriptions/ServicePackageClassName.html en la ubicación adecuada. También tendrá que proporcionar una descripción que se mostrará en el informe de Qodana y en los ajustes del IDE.
Reports class names in theservicepackages that lack theServicesuffix.
Example:
package com.example.foo.service
class SomeComponent {
/* class members */
}
Compile el complemento
Ya está todo listo: ¡es hora de compilar! Ejecute la tarea buildPlugin de Gradle y busque el artefacto build/distributions/qodana-code-inspection-0.0.1.zip disponible en el directorio de salida de Gradle. El archivo JAR se utilizará como artefacto principal en el análisis de Qodana.
Tenga en cuenta el tipo de artefacto del complemento
Qodana no admite directamente artefactos de complementos ZIP locales que incluyan archivos JAR adicionales o dependencias de terceros. Cualquier complemento se debe empaquetar como un único JAR o descomprimir en un directorio específico.
Ejecutar Qodana en un proyecto de prueba
Vamos a crear un proyecto de prueba, escrito en Kotlin, que podamos inspeccionar con Qodana ahora que lo hemos extendido con nuestro complemento. Para ejecutar el complemento de Qodana de forma local, asegúrese de que los siguientes dos componentes de software estén disponibles en su sistema:
Nuestro proyecto de prueba debería contener una clase llamada src/main/kotlin/org/intellij/sdk/qodana/service/SomeComponent.kt, que no sigue nuestra convención de código, ya que no tiene el sufijo Service. Hay dos formas de integrar el complemento de Qodana en Qodana:
- Publíquelo en JetBrains Marketplace
- Para una implementación más rápida, coloque el artefacto JAR del complemento en el directorio
.qodanade su proyecto.
Para simplificar la compilación, copie el archivo build/distributions/qodana-code-inspection-0.0.1.zip del proyecto del complemento en el archivo .qodana/qodana-code-inspection-0.0.1.zip del proyecto de prueba. Cree el directorio .qodana, si aún no existe. A continuación, extraiga el archivo con el programa o herramienta que prefiera. Qodana puede acceder al complemento en el directorio build/distributions/qodana-code-inspection.
Además, es necesario configurar Qodana para incluir nuestra inspección de código personalizada. Modifique el archivo qodana.yaml en el directorio raíz del proyecto de prueba como se indica a continuación:
version: "1.0" linter: qodana-jvm-community include: - name: org.intellij.sdk.codeInspection.ServicePackageClassNameInspection
El bloque include debe hacer referencia al nombre de clase totalmente cualificado de la inspección de código disponible en el complemento. Ahora ejecute el siguiente comando para ejecutar Qodana desde el terminal:
qodana scan --volume $PWD/.qodana/qodana-code-inspection:/opt/idea/custom-plugins/qodana-code-inspection
Esto descargará la imagen de Docker de Qodana correspondiente. Se creará y ejecutará un contenedor de Docker basado en la configuración de Qodana. Para que el complemento personalizado sea accesible dentro de la ejecución de Qodana, monte el directorio del complemento de Qodana desde el sistema de archivos local al directorio apropiado dentro del contenedor de Docker de Qodana. Tras un par de minutos, Qodana elaborará un resumen del informe y lo imprimirá en el resultado estándar.
Qodana - Detailed summary Analysis results: 1 problem detected By severity: High - 1 ------------------------------------------------------- Name Severity Problems count ------------------------------------------------------- SDK: Discouraged class name High 1 -------------------------------------------------------
Abra el informe completo en su navegador:
Do you want to open the latest report [Y/n]Yes ! Press Ctrl+C to stop serving the report Showing Qodana report from http://localhost:8080/... (10s)
Qodana mostrará que SomeComponent no cumple la convención de código proporcionada por nuestra inspección local en el complemento de Qodana.

Consejos para futuras ejecuciones
Cuando el complemento de Qodana se modifica y se reconstruye, la caché de Qodana también debe volver a crearse. En tales casos, utilice el parámetro de CLI --clear-cache para recargar todas las dependencias de la ejecución de Qodana.
qodana scan --clear-cache --volume $PWD/.qodana/qodana-code-inspection-0.0.1.jar:/opt/idea/custom-plugins/codeinspection.jar
Integrar Qodana en su IDE
El complemento de Qodana puede instalarse desde el disco en el IDE. A continuación, su inspección de código se activa e invoca automáticamente para cualquier clase de Kotlin de un proyecto. Para comprobar que funciona, vuelva al proyecto de prueba, abra la clase org.intellij.sdk.qodana.service.SomeComponent y asegúrese de que el nombre de la clase con problemas aparece subrayado. Para mayor comodidad, al pasar el ratón sobre el nombre de la clase se mostrará el resultado de la inspección del código junto con la descripción del problema. Alternativamente, puede abrir la ventana de herramientas Problems y buscar el problema en la lista de todos los problemas notificados por las inspecciones de código.
La inspección de código se comporta ahora como cualquier otra inspección proporcionada por el IDE. En Settings | Editor | Inspections | Kotlin, encontrará la inspección SDK: Discouraged class name, junto con la descripción obtenida del archivo HTML que le proporcionamos antes.
Ejecutar Qodana dentro del IDE
Con el complemento instalado, ahora también puede ejecutar Qodana desde su IDE. En la ventana de herramientas Problems, vaya a la pestaña Qodana y pulse el botón Try Locally. Qodana se configurará con el archivo qodana.yaml y se ejecutará. El informe de Qodana se encuentra directamente en la ventana de herramientas.

Complementos de Qodana y JetBrains Marketplace
Los complementos de inspección personalizados correctamente compilados y probados pueden publicarse en JetBrains Marketplace, para que no sea necesario servirlos desde el directorio .qodana. En su lugar, solo tiene que asegurarse de que la configuración de Qodana especifique un identificador de complemento público que coincida con el elemento id del descriptor del complemento.
version: "1.0" linter: qodana-jvm-community plugins: - id: com.github.novotnyr.qodanacodeinspection
El comando scan de Qodana está simplificado, ya que el montaje del directorio .qodana ya no es necesario.
qodana scan
Qodana descarga este complemento desde JetBrains Marketplace y ejecuta todas sus inspecciones, produciendo tanto un resultado de consola como un informe HTML que puede mostrarse en un navegador web.
Resumen
Hemos creado un complemento de Qodana con una inspección de código que comprueba una convención de código específica, y tenemos varias formas de ejecutarlo:
- Como un JAR colocado en el directorio
.qodanae incluido en el archivo YAML de Qodana. - Como referencia al complemento disponible públicamente en JetBrains Marketplace.
- Como un JAR instalado en el IDE, donde la inspección se aplica en una ejecución local de Qodana.
- Como un JAR instalado en el IDE, donde la inspección se incluye entre las inspecciones de código integradas.
Consulte el el ejemplo de código del IntelliJ SDK para ver demostraciones concisas tanto del complemento de Qodana como de un proyecto de prueba.
Artículo original en inglés de: