Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/103 error message if companion gradle plugin for mutation mate is missing #133

Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions .github/linters/.groovylintrc.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"extends": "recommended",
"rules": {
"BlankLineBeforePackage": {
"enabled": false
},
"JUnitPublicNonTestMethod": {
"enabled": false
},
"MethodName": {
"enabled": false
},
"CatchException": {
"enabled": false
}
"extends": "recommended",
"rules": {
"BlankLineBeforePackage": {
"enabled": false
},
"JUnitPublicNonTestMethod": {
"enabled": false
},
"MethodName": {
"enabled": false
},
"CatchException": {
"enabled": false
}
}
}
1 change: 0 additions & 1 deletion .github/linters/.yaml-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,3 @@ rules:
new-lines:
type: unix
trailing-spaces: disable

11 changes: 5 additions & 6 deletions .github/workflows/override-build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ jobs:
with:
distribution: temurin
java-version: 11

- name: Setup Gradle
uses: gradle/gradle-build-action@v2

- name: Build with Gradle
run: ./gradlew build --no-daemon
working-directory: 'pitmutationmate-override-plugin'

- name: Run Tests
run: ./gradlew test --no-daemon
working-directory: 'pitmutationmate-override-plugin'
working-directory: "pitmutationmate-override-plugin"

- name: Run Tests
run: ./gradlew test --no-daemon
working-directory: "pitmutationmate-override-plugin"
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ bin/

# MacOS
.DS_Store

# Groovy SDK
lib
1 change: 0 additions & 1 deletion pitmutationmate-override-plugin/.gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@

# These are Windows script files and should use crlf
*.bat text eol=crlf

6 changes: 3 additions & 3 deletions pitmutationmate-override-plugin/gradlew.bat
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
REM SPDX-FileCopyrightText: the original authors
REM
REM SPDX-License-Identifier: Apache-2.0
@rem SPDX-FileCopyrightText: the original authors
@rem
@rem SPDX-License-Identifier: Apache-2.0

@rem
@rem Copyright 2015 the original author or authors.
Expand Down
4 changes: 1 addition & 3 deletions pitmutationmate/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ dependencies {
implementation("org.jfree:jfreechart:1.0.19")
// https://mvnrepository.com/artifact/jfree/jcommon
implementation("org.jfree:jcommon:1.0.24")
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.0")
}

group = "com.amos.pitmutationmate"
Expand All @@ -35,9 +34,8 @@ repositories {
// Configure Gradle IntelliJ Plugin
// Read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
intellij {
version.set("2022.2.5")
version.set("2023.1")
type.set("IC") // Target IDE Platform

plugins.set(listOf("org.jetbrains.kotlin", "com.intellij.java"))
}

Expand Down
6 changes: 3 additions & 3 deletions pitmutationmate/gradlew.bat
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
REM SPDX-FileCopyrightText: the original authors
REM
REM SPDX-License-Identifier: Apache-2.0
@rem SPDX-FileCopyrightText: the original authors
@rem
@rem SPDX-License-Identifier: Apache-2.0

@rem Copyright 2015 the original author or authors.
@rem
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023

package com.amos.pitmutationmate.pitmutationmate.plugincheck

import org.codehaus.groovy.ast.CodeVisitorSupport
import org.codehaus.groovy.ast.expr.MethodCallExpression

class PluginCheckerGroovy : CodeVisitorSupport() {

var pitestPluginAvailable = false
var companionPluginAvailable = false

override fun visitMethodCallExpression(call: MethodCallExpression?) {
val method = call?.methodAsString
if (method.equals("plugins") || method.equals("apply") || method.equals("version")) {
super.visitMethodCallExpression(call)
} else if (method.equals("id")) {
if (call != null) {
val pluginName = call.arguments.text
if (pluginName.contains("pitest")) {
lheimbs marked this conversation as resolved.
Show resolved Hide resolved
pitestPluginAvailable = true
}
if (pluginName.contains("io.github.amosproj.pitmutationmate.override")) {
companionPluginAvailable = true
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023

package com.amos.pitmutationmate.pitmutationmate.plugincheck

import org.jetbrains.kotlin.idea.structuralsearch.visitor.KotlinRecursiveElementVisitor
import org.jetbrains.kotlin.psi.KtCallExpression

class PluginCheckerKotlin : KotlinRecursiveElementVisitor() {

var pitestPluginAvailable = false
var companionPluginAvailable = false

override fun visitCallExpression(expression: KtCallExpression) {
val method = expression.calleeExpression?.text
if (method.equals("plugins")) {
expression.acceptChildren(this)
}
if (method.equals("id")) {
if (expression.valueArgumentList != null) {
for (arg in expression.valueArgumentList!!.arguments) {
val pluginName = arg.text
if (pluginName.contains("pitest")) {
lheimbs marked this conversation as resolved.
Show resolved Hide resolved
pitestPluginAvailable = true
}
if (pluginName.contains("io.github.amosproj.pitmutationmate.override")) {
companionPluginAvailable = true
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: 2023

package com.amos.pitmutationmate.pitmutationmate.plugincheck

import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.startup.ProjectActivity
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.psi.PsiManager
import org.apache.commons.io.IOUtils
import org.codehaus.groovy.ast.builder.AstBuilder
import java.io.File
import java.io.FileInputStream

class StartupPluginChecker : ProjectActivity {

override suspend fun execute(project: Project) {
ApplicationManager.getApplication().invokeLater {
checkGroovyBuildFile(project)
checkKotlinBuildFile(project)
}
}

private fun checkKotlinBuildFile(project: Project) {
val buildFileName = "build.gradle.kts"
val kotlinBuildFile = File(project.basePath + "/$buildFileName")
if (kotlinBuildFile.exists()) {
val virtualFile = LocalFileSystem.getInstance().findFileByIoFile(kotlinBuildFile)
if (virtualFile != null) {
val psiFile = PsiManager.getInstance(project).findFile(virtualFile)
val pluginCheckerKotlin = PluginCheckerKotlin()
psiFile?.node?.psi?.accept(pluginCheckerKotlin)
val pitestPluginText = "id(\"info.solidsoft.pitest\") version \"1.15.0\""
val companionPluginText = "id(\"io.github.amosproj.pitmutationmate.override\") version \"1.0\""
nikomall34 marked this conversation as resolved.
Show resolved Hide resolved
throwErrorMessage(
pluginCheckerKotlin.pitestPluginAvailable,
pluginCheckerKotlin.companionPluginAvailable,
buildFileName,
project,
pitestPluginText,
companionPluginText
)
}
}
}

private fun checkGroovyBuildFile(project: Project) {
val buildFileName = "build.gradle"
val groovyBuildFile = File(project.basePath + "/$buildFileName")
if (groovyBuildFile.exists()) {
val builder = AstBuilder()
val nodes = builder.buildFromString(
IOUtils.toString(
FileInputStream(groovyBuildFile),
"UTF-8"
)
)
val pluginCheckerGroovy = PluginCheckerGroovy()
for (node in nodes) {
node.visit(pluginCheckerGroovy)
}
val pitestPluginText = "id 'info.solidsoft.pitest' version '1.15.0'"
val companionPluginText = "id 'io.github.amosproj.pitmutationmate.override' version '1.0'"
nikomall34 marked this conversation as resolved.
Show resolved Hide resolved
throwErrorMessage(
pluginCheckerGroovy.pitestPluginAvailable,
pluginCheckerGroovy.companionPluginAvailable,
buildFileName,
project,
pitestPluginText,
companionPluginText
)
}
}

private fun throwErrorMessage(
pitestPluginAvailable: Boolean,
companionPluginAvailable: Boolean,
buildFileName: String,
project: Project,
pitestPluginText: String,
companionPluginText: String
) {
var errorMessage = ""
if (!pitestPluginAvailable) {
errorMessage += String.format(
ERROR_MESSAGE_PITEST_PLUGIN_MISSING,
buildFileName,
pitestPluginText
)
}
if (!companionPluginAvailable) {
errorMessage += String.format(
ERROR_MESSAGE_COMPANION_PLUGIN_MISSING,
buildFileName,
companionPluginText
)
}
if (errorMessage.isNotEmpty()) {
Messages.showErrorDialog(project, errorMessage, ERROR_MESSAGE_TITLE)
}
}

companion object {
private const val ERROR_MESSAGE_TITLE = "Plugins for PITMutationPlugin are missing"
private const val ERROR_MESSAGE_PITEST_PLUGIN_MISSING = "The pitest gradle Plugin is missing.\n" +
"Please add a Gradle Pitest Plugin to the %s file like the following:\n" +
"%s\nAnd see the pitest docs for missing configurations of pitest\n\n"
private const val ERROR_MESSAGE_COMPANION_PLUGIN_MISSING = "The Companion Plugin is missing.\n" +
"Please add the following line to your %s file:\n%s\n\n"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.MessageType
import com.intellij.openapi.wm.ToolWindowManager
import org.jetbrains.kotlin.idea.gradleTooling.get
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.util.*

/**
* A simple UDP server that listens on a given port and prints the received messages.
Expand Down Expand Up @@ -65,11 +65,23 @@ class UdpMessagingServer(private val project: Project) {

if (overrideClassFQN != null && message.contains(overrideClassFQN)) {
// class was successfully overridden. Notify the user
ToolWindowManager.getInstance(project).notifyByBalloon(
"Pitest Result",
val proj = this.project
ToolWindowManager.getInstance(proj).notifyByBalloon(
"Pitest",
MessageType.INFO,
"<p>Successfully applied pitest target class</p><p>$overrideClassFQN.</p>"
)

val timer = Timer(true)
timer.schedule(
object : TimerTask() {
override fun run() {
ToolWindowManager.getInstance(proj).getToolWindowBalloon("Pitest")?.hide()
timer.cancel()
}
},
6000L
)
lheimbs marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
10 changes: 4 additions & 6 deletions pitmutationmate/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,18 @@
<!-- Product and plugin compatibility requirements.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-compatibility.html -->
<depends>com.intellij.java</depends>
<depends>org.jetbrains.kotlin</depends>


<!-- Extension points defined by the plugin.
Read more: https://plugins.jetbrains.com/docs/intellij/plugin-extension-points.html -->
<extensions defaultExtensionNs="com.intellij">

<toolWindow id="Pitest" secondary="false" icon="AllIcons.Toolwindows.WebToolWindow" anchor="right"
<toolWindow id="Pitest" secondary="false" icon="AllIcons.Toolwindows.WebToolWindow" anchor="right"
factoryClass="com.amos.pitmutationmate.pitmutationmate.MutationTestToolWindowFactory"/>

<runLineMarkerContributor implementationClass="com.amos.pitmutationmate.pitmutationmate.actions.GutterMarker"
language=""/>

<configurationType
implementation="com.amos.pitmutationmate.pitmutationmate.configuration.RunConfigurationType"/>
<configurationType implementation="com.amos.pitmutationmate.pitmutationmate.configuration.RunConfigurationType"/>
<backgroundPostStartupActivity implementation="com.amos.pitmutationmate.pitmutationmate.plugincheck.StartupPluginChecker"/>
</extensions>
<actions>
<action id="com.amos.pitmutationmate.pitmutationmate.actions.ToolMenuAction"
Expand Down
Loading