Skip to content

Commit

Permalink
Suppress GoLand unused function warning on API
Browse files Browse the repository at this point in the history
* Refactor annotator for code sharing with new component
* Update Gradle and dependencies
* Bump JDK to 17 to match official guidance
* Minor cleanups (ignored files, unused imports and variables)
* Bump version to 0.3.0
  • Loading branch information
CL-Jeremy committed Jan 12, 2025
1 parent 0969c5a commit 24d9ffc
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 46 deletions.
17 changes: 0 additions & 17 deletions .idea/gradle.xml

This file was deleted.

9 changes: 4 additions & 5 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import org.jetbrains.changelog.Changelog
import org.jetbrains.changelog.markdownToHTML
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

fun properties(key: String) = providers.gradleProperty(key)
fun environment(key: String) = providers.environmentVariable(key)
Expand All @@ -9,11 +8,11 @@ plugins {
// Java support
id("java")
// Kotlin support
id("org.jetbrains.kotlin.jvm") version "1.8.10"
id("org.jetbrains.kotlin.jvm") version "1.9.25"
// Gradle IntelliJ Plugin
id("org.jetbrains.intellij") version "1.13.2"
id("org.jetbrains.intellij") version "1.17.2"
// Gradle Changelog Plugin
id("org.jetbrains.changelog") version "2.0.0"
id("org.jetbrains.changelog") version "2.2.1"
// Gradle Qodana Plugin
id("org.jetbrains.qodana") version "0.1.13"
// Gradle Kover Plugin
Expand All @@ -30,7 +29,7 @@ repositories {

// Set the JVM language level used to build the project. Use Java 11 for 2020.3+, and Java 17 for 2022.2+.
kotlin {
jvmToolchain(11)
jvmToolchain(17)
}

// Configure Gradle IntelliJ Plugin - read more: https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
pluginGroup = dev.encore.intellij
pluginName = Encore
# SemVer format -> https://semver.org
pluginVersion = 0.2.0
pluginVersion = 0.3.0

# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
# for insight into build numbers and IntelliJ Platform versions.
Expand All @@ -21,7 +21,7 @@ platformDownloadSources = true
platformPlugins = org.jetbrains.plugins.go, com.intellij.database

# Gradle Releases -> https://github.com/gradle/gradle/releases
gradleVersion = 8.0.2
gradleVersion = 8.12

# Opt-out flag for bundling Kotlin standard library.
# See https://jb.gg/intellij-platform-kotlin-stdlib for details.
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
55 changes: 34 additions & 21 deletions src/main/kotlin/dev/encore/intellij/annotators/ApiDecls.kt
Original file line number Diff line number Diff line change
@@ -1,55 +1,55 @@
package dev.encore.intellij.annotators

import com.goide.highlighting.GoSyntaxHighlightingColors
import com.goide.psi.GoFunctionDeclaration
import com.intellij.codeInspection.ProblemHighlightType
import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.lang.annotation.Annotator
import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors
import com.intellij.openapi.editor.markup.GutterIconRenderer
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil

class ApiDecls : Annotator {
override fun annotate(element: PsiElement, holder: AnnotationHolder) {
// If it's not a comment and doesn't start with "//encore:", return
// as we're not interested in it
if (element !is PsiComment) {
// If it's not a comment, doesn't start with "//encore:" or is not
// followed by a func definition, return as we're not interested in it
if (element !is PsiComment || PsiTreeUtil.skipWhitespacesForward(element) !is GoFunctionDeclaration) {
return
}
val comment: PsiComment = element
if (!comment.text.startsWith(API_DECL_PREFIX)) {
return
}
val parts = comment.text.removePrefix("//").split(" ")
if (parts.isEmpty() || !PREFIXES.containsKey(parts[0]) ) {

// Parse the comment. Return if prefix is not known to us
val (prefix, cfg, args) = parseApiAnnotation(comment)
if (cfg == null) {
return
}

val cfg: DeclCfg = PREFIXES[parts[0]]!!
// Skip the initial "//"
val startOffset = comment.textRange.startOffset + 2


// Highlight the "//encore:" part of the comment as a comment keyword
val directiveRange = TextRange.from(comment.textRange.startOffset + 2, parts[0].length)
// Highlight the "encore:" part of the comment as a comment keyword
val directiveRange = TextRange.from(startOffset, prefix.length)
holder.newSilentAnnotation(HighlightSeverity.INFORMATION)
.range(directiveRange)
.textAttributes(GoSyntaxHighlightingColors.COMMENT_KEYWORD)
.tooltip(cfg.tooltip)
.create()

// Highlight the rest of the comment
var lastIndex = comment.textRange.startOffset + parts[0].length + 3
var lastOffset = startOffset + prefix.length + 1
val used = mutableSetOf<String>()

for (part in parts.drop(1)) {
for (part in args) {
if (part.contains('=')) {
// It's a field
val splitPoint = part.indexOf('=')
val fieldName = part.take(splitPoint)
val fieldValue = part.drop(splitPoint + 1)
val nameRange = TextRange.from(lastIndex, splitPoint)
val valueRange = TextRange.from(lastIndex + splitPoint + 1, fieldValue.length)
val nameRange = TextRange.from(lastOffset, splitPoint)
val valueRange = TextRange.from(lastOffset + splitPoint + 1, fieldValue.length)


// Check it's not already used once
Expand All @@ -74,13 +74,13 @@ class ApiDecls : Annotator {
.create()
}

highlightFieldValue(holder, cfg, fieldName, fieldValue, valueRange)
highlightFieldValue(holder, fieldName, fieldValue, valueRange)

used.add(fieldName)

} else {
// It's an option
val partRange = TextRange.from(lastIndex, part.length)
val partRange = TextRange.from(lastOffset, part.length)

// Check it's not already used once
if (used.contains(part)) {
Expand All @@ -106,11 +106,11 @@ class ApiDecls : Annotator {
used.add(part)
}

lastIndex += part.length + 1
lastOffset += part.length + 1
}
}

private fun highlightFieldValue(holder: AnnotationHolder, cfg: DeclCfg, fieldName: String, fieldValue: String, range: TextRange) {
private fun highlightFieldValue(holder: AnnotationHolder, fieldName: String, fieldValue: String, range: TextRange) {
if (fieldName == "path" && (fieldValue.contains(":") || fieldValue.contains("*"))) {
// highlight each segment starting with ":" as a different colour
var lastIndex = range.startOffset
Expand Down Expand Up @@ -182,6 +182,19 @@ class ApiDecls : Annotator {
arrayOf("target"),
)
)

fun isApiAnnotation(comment: PsiComment) = parseApiAnnotation(comment).second != null

private fun parseApiAnnotation(comment: PsiComment): Triple<String, DeclCfg?, List<String>> {
val text = comment.text
if (!text.startsWith(API_DECL_PREFIX)) {
return Triple("", null, emptyList())
}
val parts = text.removePrefix("//").split(" ")
val prefix = parts.getOrNull(0) ?: ""

return Triple(prefix, PREFIXES[prefix], parts.drop(1))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dev.encore.intellij.inspections

import com.goide.psi.GoFunctionDeclaration
import com.intellij.codeInspection.InspectionSuppressor
import com.intellij.codeInspection.SuppressQuickFix
import com.intellij.psi.PsiComment
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import dev.encore.intellij.annotators.ApiDecls.Companion.isApiAnnotation

class ApiUnusedSuppressor : InspectionSuppressor {
companion object {
private const val TOOL_ID = "GoUnusedExportedFunction"
}

override fun isSuppressedFor(element: PsiElement, toolId: String): Boolean {
if (element !is GoFunctionDeclaration || toolId != TOOL_ID) {
return false
}
val prevElement = PsiTreeUtil.skipWhitespacesBackward(element)
if (prevElement !is PsiComment) {
return false
}
val comment: PsiComment = prevElement
return isApiAnnotation(comment)
}

override fun getSuppressActions(element: PsiElement?, toolId: String) = SuppressQuickFix.EMPTY_ARRAY!!

}
2 changes: 2 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
id="dev.encore.intellij.settings.Settings"
displayName="Encore"/>
/>

<lang.inspectionSuppressor language="go" implementationClass="dev.encore.intellij.inspections.ApiUnusedSuppressor"/>
</extensions>

<extensions defaultExtensionNs="com.goide">
Expand Down

0 comments on commit 24d9ffc

Please sign in to comment.