├── .gitignore ├── LICENSE ├── README.md ├── build.gradle.kts ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── renovate.json ├── settings.gradle.kts └── src └── main ├── java └── dev │ └── rollczi │ └── litecommands │ └── intellijplugin │ ├── annotation │ ├── AnnotationFactory.java │ └── AnnotationHolder.java │ ├── api │ ├── Argument.java │ ├── CommandNode.java │ ├── ExecutorNode.java │ ├── Node.java │ ├── PermissionEntry.java │ ├── PermissionsDefinition.java │ ├── PermissionsOwner.java │ └── psijava │ │ ├── PsiJavaAbstractNode.java │ │ ├── PsiJavaArgument.java │ │ ├── PsiJavaCommandNode.java │ │ ├── PsiJavaExecutorNode.java │ │ ├── PsiJavaPermissionEntry.java │ │ └── PsiJavaPermissionsDefinition.java │ ├── icon │ └── LiteIcons.java │ ├── inlay │ ├── InlayHintsConfigurable.java │ ├── InlayHintsIconPresentation.java │ ├── InlayPopupNewActions.java │ ├── LiteInlayHints.java │ ├── LiteInlayHintsCollector.java │ └── ref │ │ ├── ArgumentPsiReferenceProvider.java │ │ ├── LitePsiReferenceContributor.java │ │ └── SimpleReference.java │ ├── inspection │ ├── LiteInspection.java │ ├── LiteInspectionProvider.java │ ├── annotation │ │ └── LiteNullabilityAnnotationPackage.java │ ├── executor │ │ └── ExecutorNotAnnotatedParameterInspection.java │ ├── mapper │ │ ├── AnnotationMapper.java │ │ ├── AnnotationMapperAttributeSchema.java │ │ ├── AnnotationMapperSchema.java │ │ ├── AnnotationReplaceQuickFix.java │ │ ├── AnnotationVisitor.java │ │ ├── Attribute.java │ │ ├── AttributeType.java │ │ ├── AttributeValue.java │ │ ├── LegacyAnnotationInspectionTool.java │ │ ├── ReplaceWithValidValueQuickFix.java │ │ ├── ValidationAnnotationInspectionTool.java │ │ ├── legacy │ │ │ ├── LegacyArgInspection.java │ │ │ ├── LegacyExecuteInspection.java │ │ │ ├── LegacyJoinInspection.java │ │ │ ├── LegacyPermissionInspection.java │ │ │ ├── LegacyRouteInspection.java │ │ │ └── LegacySectionInspection.java │ │ └── validation │ │ │ ├── CommandNameValidUtils.java │ │ │ ├── CommandValidationInspection.java │ │ │ ├── ExecuteValidationInspection.java │ │ │ ├── RouteQuickFix.java │ │ │ ├── ShortcutValidationInspection.java │ │ │ └── SingleRouteQuickFix.java │ └── parameter │ │ ├── LiteralAnnotationInspection.java │ │ ├── ParameterMixedAnnotationsInspection.java │ │ ├── ParameterNullableOptionalPrimitiveInspection.java │ │ ├── ParameterNullableOptionalWrappedInspection.java │ │ └── VarargsAnnotationInspection.java │ ├── marker │ ├── LiteLineMarkerDescriptor.java │ ├── LiteLineMarkerInfo.java │ ├── command │ │ ├── AddButton.java │ │ ├── CommandComponent.java │ │ ├── CommandMarker.java │ │ ├── EditButton.java │ │ ├── ExecutorsComponent.java │ │ ├── PermissionsComponent.java │ │ └── dialog │ │ │ ├── EditDialog.java │ │ │ ├── EditDialogPanel.java │ │ │ └── TextReference.java │ ├── executor │ │ ├── ExecutorComponent.java │ │ └── ExecutorMarker.java │ └── ui │ │ └── ExecutorBadgeFactory.java │ ├── navigatable │ └── NavigatableReference.java │ ├── popup │ └── LitePopupFactory.java │ ├── quickfix │ ├── ChangeParameterTypeQuickFix.java │ ├── ReplaceQuickFix.java │ └── WrapParameterTypeQuickFix.java │ ├── settings │ ├── LiteCommandsConfigurable.java │ ├── LiteCommandsSettings.java │ └── LiteSettingsBox.java │ ├── suppressor │ ├── ClassUnusedInspectSuppressor.java │ ├── ConstructorUnusedInspectSuppressor.java │ ├── ExecutorUnusedInspectSuppressor.java │ ├── NullableProblemsPrimitiveSuppressor.java │ ├── OptionalArgumentSuppressor.java │ └── SuppressUtils.java │ ├── table │ ├── LiteTableView.java │ ├── LiteToolbarDecorator.java │ └── TextColumnInfo.java │ ├── template │ └── LiteCommandsTemplatesAction.java │ ├── ui │ ├── LiteActionBadge.java │ ├── LiteArc.java │ ├── LiteBadge.java │ ├── LiteBox.java │ ├── LiteColors.java │ ├── LiteComponent.java │ ├── LiteMargin.java │ └── LiteTitledSeparator.java │ ├── usage │ ├── Usage.java │ ├── UsageActionHandler.java │ ├── UsageFindUsagesDialog.java │ ├── UsageProvider.java │ └── UsageService.java │ └── util │ ├── HighlightUtil.java │ ├── IdeaEmptyTask.java │ ├── IdeaTask.java │ ├── IdeaTaskType.java │ ├── LiteAnnotationChecks.java │ ├── LiteTypeChecks.java │ ├── LiteTypeSearcher.java │ ├── PsiAnnotationUtil.java │ ├── PsiImportUtil.java │ ├── PsiPrimitiveUtil.java │ └── PsiValue.java └── resources ├── META-INF ├── plugin.xml └── pluginIcon.svg ├── assets └── icons │ ├── expUi │ ├── application.svg │ ├── applicationRemote.svg │ ├── applicationRemote_dark.svg │ ├── application_dark.svg │ ├── columnGoldKey.svg │ ├── columnGoldKeyDotIndex.svg │ ├── columnGoldKeyDotIndex_dark.svg │ ├── columnGoldKey_dark.svg │ ├── frame.svg │ ├── frame_dark.svg │ ├── goldKey.svg │ ├── goldKey_dark.svg │ ├── groupByModule.svg │ ├── groupByModule_dark.svg │ ├── inlayRenameInComments.svg │ ├── inlayRenameInCommentsActive.svg │ ├── inlayRenameInCommentsActive_dark.svg │ ├── inlayRenameInComments_dark.svg │ ├── mongoFieldGoldKey.svg │ ├── mongoFieldGoldKey_dark.svg │ ├── ocdRunConfiguration.svg │ ├── ocdRunConfiguration_dark.svg │ ├── runParatest.svg │ ├── runParatest_dark.svg │ ├── showCurrentFrame.svg │ └── showCurrentFrame_dark.svg │ ├── litecommandsIcon_class.svg │ ├── litecommandsIcon_class_dark.svg │ ├── litecommandsIcon_class_root.svg │ ├── litecommandsIcon_class_root_dark.svg │ ├── litecommandsIcon_kotlin_class.svg │ ├── litecommandsIcon_kotlin_class_dark.svg │ ├── litecommandsIcon_kotlin_root_class.svg │ ├── litecommandsIcon_kotlin_root_class_dark.svg │ └── litecommandsLogo.svg ├── fileTemplates └── internal │ ├── LiteCommands Command Java.java.ft │ ├── LiteCommands Command Kotlin.kt.ft │ ├── LiteCommands Root Command Java.java.ft │ └── LiteCommands Root Command Kotlin.kt.ft ├── inspectionDescriptions ├── ExecuteValidation.html ├── ExecutorNotAnnotatedParameter.html ├── LegacyArg.html ├── LegacyExecute.html ├── LegacyJoin.html ├── LegacyPermission.html ├── LegacyRoute.html ├── LegacySection.html ├── LiteralAnnotation.html ├── ParameterMixedAnnotations.html ├── ParameterNullableOptionalPrimitive.html ├── ParameterNullableOptionalWrapped.html ├── ParameterOptionalIsPrimitive.html ├── RouteValidation.html └── VarargsAnnotation.html └── messages └── LiteCommandsBundle.properties /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build 3 | .idea 4 | .intellijPlatform 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | [![dependency](https://repo.panda-lang.org/api/badge/latest/releases/dev/rollczi/litecommands-core?color=9372f9&name=Version)](https://repo.panda-lang.org/#/releases/dev/rollczi/litecommands) 6 |
7 | 8 |
9 | 10 | banner 11 |

12 | 13 | [![Discord](https://raw.githubusercontent.com/intergrav/devins-badges/v3/assets/cozy/social/discord-plural_vector.svg)](https://discord.gg/6cUhkj6uZJ) 14 | [![Sponsor](https://raw.githubusercontent.com/intergrav/devins-badges/v3/assets/cozy/donate/ghsponsors-singular_vector.svg)](https://github.com/sponsors/Rollczi) 15 | [![Gradle](https://raw.githubusercontent.com/intergrav/devins-badges/v3/assets/cozy/built-with/gradle_vector.svg)](https://gradle.org/) 16 | [![Java](https://raw.githubusercontent.com/intergrav/devins-badges/v3/assets/cozy/built-with/java17_vector.svg)](https://www.java.com/) 17 | 18 | ### LiteCommands - IntelliJ IDEA Plugin 19 | 20 |
21 | 22 | With LiteCommands plugin, you can easily develop your commands within the **IntelliJ IDEA** environment. 23 | The plugin provides **annotation inspections**, **tools** for creating new command classes, 24 | **syntax highlighting**, **code completion**, 25 | and other useful features to make your development experience smoother and more efficient. 26 | 27 | [LiteCommands](https://github.com/Rollczi/LiteCommands) is an annotation-based command framework 28 | that can be used with Velocity, Bukkit, Paper, BungeeCord, Minestom, Sponge, Fabric, JDA and future implementations. 29 | 30 | ## Links 31 | - [Discord](https://discord.gg/6cUhkj6uZJ) 32 | - [Plugin](https://plugins.jetbrains.com/plugin/20799-litecommands) 33 | - [Documentation](https://docs.rollczi.dev) 34 | - [GitHub](https://github.com/Rollczi/LiteCommands) 35 | 36 | 37 | 38 | ## Features 39 | 40 | - [x] Annotation inspections to easily identify and fix errors in your command code 41 | - [x] Quick fixes for common issues with LiteCommands code 42 | - [x] Syntax highlighting to make your code easier to read and understand 43 | - [x] Tools for creating new command classes and generating command method templates 44 | - [ ] Code completion for LiteCommands annotations and methods 45 | 46 | ## Installation 47 | 48 | To install 🔌 LiteCommands plugin, follow these steps: 49 | 50 | 1. Open the IntelliJ IDEA plugin repository by going to `Preferences` > `Plugins` > `Marketplace`. 51 | 2. Search for "LiteCommands" in the search bar. 52 | 3. Click the `Install` button for the 🔌 LiteCommands plugin. 53 | 4. Restart IntelliJ IDEA for the changes to take effect. 54 | 55 | ## Usage 56 | 57 | Once 🔌 LiteCommands plugin is installed, you can use it to develop and test your commands. To create a new LiteCommands project, follow these steps: 58 | 59 | 1. Set up your Java project with either Maven or Gradle. 60 | 2. Add the LiteCommands dependency to your dependencies. [[See more]](https://docs.rollczi.dev/documentation/litecommands/getting-started/dependencies.html) 61 | 3. Start writing your commands! The LiteCommands plugin will make it easier for you to write code. 62 | 63 | For more detailed instructions on setting up LiteCommands in your project, please see the [Getting Started](https://docs.rollczi.dev/documentation/litecommands/getting-started.html) guide in the LiteCommands documentation. 64 | 65 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.changelog.markdownToHTML 2 | 3 | plugins { 4 | id("java") 5 | id("org.jetbrains.kotlin.jvm") version "2.0.21" 6 | id("org.jetbrains.intellij.platform") version "2.5.0" 7 | id("org.jetbrains.changelog") version "2.2.1" 8 | } 9 | 10 | group = "dev.rollczi" 11 | version = "3.9.7" 12 | 13 | repositories { 14 | mavenCentral() 15 | maven("https://repo.eternalcode.pl/releases") 16 | maven("https://repo.eternalcode.pl/snapshots") 17 | 18 | intellijPlatform { 19 | defaultRepositories() 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation("dev.rollczi:litecommands-framework:${version}") 25 | intellijPlatform { 26 | intellijIdeaCommunity("2025.1") 27 | bundledPlugins("com.intellij.java", "org.jetbrains.kotlin") 28 | instrumentationTools() 29 | pluginVerifier() 30 | zipSigner() 31 | } 32 | } 33 | 34 | intellijPlatform { 35 | projectName = project.name 36 | 37 | pluginConfiguration { 38 | name = "LiteCommands" 39 | id = "dev.rollczi.litecommands.intellijplugin" 40 | version.set(project.version.toString()) 41 | description = readDescriptionFrom("README.md") 42 | 43 | ideaVersion { 44 | sinceBuild = "242" 45 | untilBuild = "251.*" 46 | } 47 | } 48 | 49 | signing { 50 | certificateChain.set(providers.environmentVariable("CERTIFICATE_CHAIN")) 51 | privateKey.set(providers.environmentVariable("PRIVATE_KEY")) 52 | password.set(providers.environmentVariable("PRIVATE_KEY_PASSWORD")) 53 | } 54 | 55 | publishing { 56 | token.set(providers.environmentVariable("PUBLISH_TOKEN")) 57 | } 58 | 59 | pluginVerification { 60 | ides { 61 | recommended() 62 | } 63 | } 64 | } 65 | 66 | java { 67 | toolchain.languageVersion.set(JavaLanguageVersion.of(17)) 68 | } 69 | 70 | kotlin { 71 | jvmToolchain(17) 72 | } 73 | 74 | fun readDescriptionFrom(file: String) = providers.fileContents(layout.projectDirectory.file(file)).asText.map { 75 | val start = "" 76 | val end = "" 77 | 78 | with(it.lines()) { 79 | if (!containsAll(listOf(start, end))) { 80 | throw GradleException("Plugin description section not found in README.md:\n$start ... $end") 81 | } 82 | subList(indexOf(start) + 1, indexOf(end)).joinToString("\n").let(::markdownToHTML) 83 | } 84 | } -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rollczi/LiteCommands-IntelliJPlugin/e5bfb5a481130724348ce3f68e16cc5b00c0341e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "dependencyDashboard": true, 4 | "extends": [ 5 | "config:recommended" 6 | ], 7 | "groupName": "all dependencies", 8 | "groupSlug": "all", 9 | "lockFileMaintenance": { 10 | "enabled": false 11 | }, 12 | "separateMajorMinor": true, 13 | "pruneStaleBranches": true, 14 | "commitMessagePrefix": "dependency:", 15 | "packageRules": [ 16 | { 17 | "groupName": "patch", 18 | "matchUpdateTypes": [ 19 | "patch" 20 | ], 21 | "automerge": true, 22 | "matchPackageNames": [ 23 | "*", 24 | "!/org.spigotmc*/", 25 | "!/net.fabricmc*/" 26 | ] 27 | }, 28 | { 29 | "groupName": "minor", 30 | "matchUpdateTypes": [ 31 | "minor" 32 | ], 33 | "automerge": true, 34 | "matchPackageNames": [ 35 | "*", 36 | "!/org.spigotmc*/", 37 | "!/net.fabricmc*/" 38 | ] 39 | }, 40 | { 41 | "groupName": "all-major", 42 | "matchUpdateTypes": [ 43 | "major" 44 | ], 45 | "automerge": false, 46 | "matchPackageNames": [ 47 | "*", 48 | "!/org.spigotmc*/", 49 | "!/net.fabricmc*/" 50 | ] 51 | } 52 | ] 53 | } 54 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenCentral() 4 | gradlePluginPortal() 5 | } 6 | } 7 | 8 | rootProject.name = "LiteCommands-IntelliJPlugin" -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/annotation/AnnotationHolder.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.annotation; 2 | 3 | import com.intellij.psi.PsiAnnotation; 4 | 5 | import java.lang.annotation.Annotation; 6 | 7 | public class AnnotationHolder { 8 | 9 | private final PsiAnnotation annotation; 10 | private final A instance; 11 | 12 | public AnnotationHolder(PsiAnnotation annotation, A instance) { 13 | this.annotation = annotation; 14 | this.instance = instance; 15 | } 16 | 17 | public PsiAnnotation asPsi() { 18 | return annotation; 19 | } 20 | 21 | public A asAnnotation() { 22 | return instance; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/Argument.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api; 2 | 3 | public interface Argument { 4 | 5 | String name(); 6 | 7 | String formattedName(); 8 | 9 | String type(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/CommandNode.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api; 2 | 3 | import com.intellij.psi.PsiFile; 4 | import dev.rollczi.litecommands.intellijplugin.navigatable.NavigatableReference; 5 | import java.util.List; 6 | 7 | public interface CommandNode extends Node { 8 | 9 | @Override 10 | String name(); 11 | 12 | @Override 13 | void name(String name); 14 | 15 | @Override 16 | NavigatableReference navigateToName(); 17 | 18 | @Override 19 | List aliases(); 20 | 21 | @Override 22 | void aliases(List aliases); 23 | 24 | @Override 25 | NavigatableReference navigateToAlias(String alias); 26 | 27 | @Override 28 | PermissionsDefinition permissionsDefinition(); 29 | 30 | List executors(); 31 | 32 | boolean hasExecutors(); 33 | 34 | PsiFile getFile(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/ExecutorNode.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.navigatable.NavigatableReference; 4 | import java.util.List; 5 | import java.util.StringJoiner; 6 | 7 | public interface ExecutorNode extends Node { 8 | 9 | @Override 10 | String name(); 11 | 12 | @Override 13 | void name(String name); 14 | 15 | @Override 16 | NavigatableReference navigateToName(); 17 | 18 | default String structure() { 19 | String executorName = this.name() + " "; 20 | 21 | if (this.name().isEmpty()) { 22 | executorName = ""; 23 | } 24 | 25 | StringJoiner arguments = new StringJoiner(" "); 26 | 27 | for (Argument argument : this.arguments()) { 28 | arguments.add(argument.formattedName()); 29 | } 30 | 31 | return "/" + this.parent().name() + " " + executorName + arguments; 32 | } 33 | 34 | @Override 35 | List aliases(); 36 | 37 | @Override 38 | void aliases(List aliases); 39 | 40 | @Override 41 | NavigatableReference navigateToAlias(String alias); 42 | 43 | @Override 44 | PermissionsDefinition permissionsDefinition(); 45 | 46 | CommandNode parent(); 47 | 48 | List arguments(); 49 | 50 | NavigatableReference navigatable(); 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/Node.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api; 2 | 3 | import com.intellij.pom.Navigatable; 4 | import java.util.List; 5 | 6 | public interface Node extends PermissionsOwner { 7 | 8 | String name(); 9 | 10 | void name(String name); 11 | 12 | Navigatable navigateToName(); 13 | 14 | List aliases(); 15 | 16 | void aliases(List aliases); 17 | 18 | Navigatable navigateToAlias(String alias); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/PermissionEntry.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.navigatable.NavigatableReference; 4 | 5 | public interface PermissionEntry { 6 | 7 | String name(); 8 | 9 | NavigatableReference navigatable(); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/PermissionsDefinition.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.navigatable.NavigatableReference; 4 | import java.util.List; 5 | 6 | public interface PermissionsDefinition { 7 | 8 | List permissions(); 9 | 10 | void permissions(List permissions); 11 | 12 | boolean isEmpty(); 13 | 14 | NavigatableReference navigatable(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/PermissionsOwner.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api; 2 | 3 | public interface PermissionsOwner { 4 | 5 | PermissionsDefinition permissionsDefinition(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/psijava/PsiJavaArgument.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api.psijava; 2 | 3 | import com.intellij.psi.PsiParameter; 4 | import dev.rollczi.litecommands.intellijplugin.api.Argument; 5 | import java.util.function.Function; 6 | 7 | class PsiJavaArgument implements Argument { 8 | 9 | static final Function ARG = rawValue -> "<" + rawValue + ">"; 10 | static final Function STATIC_VALUE = rawValue -> rawValue; 11 | static final Function OPTIONAL = rawValue -> "[" + rawValue + "]"; 12 | static final Function JOIN = rawValue -> "<" + rawValue + "...>"; 13 | static final Function ARRAY = rawValue -> "[" + rawValue + "...]"; 14 | 15 | 16 | private final PsiJavaExecutorNode parent; 17 | private final PsiParameter psiParameter; 18 | private final String name; 19 | private final Function formatter; 20 | 21 | public PsiJavaArgument(PsiJavaExecutorNode parent, PsiParameter psiParameter, String name, Function formatter) { 22 | this.parent = parent; 23 | this.psiParameter = psiParameter; 24 | this.formatter = formatter; 25 | this.name = name.isBlank() ? psiParameter.getName() : name; 26 | } 27 | 28 | @Override 29 | public String name() { 30 | return name; 31 | } 32 | 33 | @Override 34 | public String formattedName() { 35 | return formatter.apply(name); 36 | } 37 | 38 | @Override 39 | public String type() { 40 | return psiParameter.getType().getCanonicalText(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/psijava/PsiJavaCommandNode.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api.psijava; 2 | 3 | import com.intellij.psi.PsiAnnotation; 4 | import com.intellij.psi.PsiClass; 5 | import com.intellij.psi.PsiFile; 6 | import com.intellij.psi.PsiMethod; 7 | import dev.rollczi.litecommands.annotations.command.Command; 8 | import dev.rollczi.litecommands.annotations.execute.Execute; 9 | import dev.rollczi.litecommands.intellijplugin.api.CommandNode; 10 | import dev.rollczi.litecommands.intellijplugin.api.ExecutorNode; 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class PsiJavaCommandNode extends PsiJavaAbstractNode implements CommandNode { 16 | 17 | private final PsiClass psiClass; 18 | 19 | public PsiJavaCommandNode(PsiClass psiClass) { 20 | super(psiClass, Command.class, "name", "aliases"); 21 | this.psiClass = psiClass; 22 | } 23 | 24 | @Override 25 | public List executors() { 26 | List executors = new ArrayList<>(); 27 | 28 | for (PsiMethod method : psiClass.getMethods()) { 29 | PsiAnnotation annotation = method.getAnnotation(Execute.class.getName()); 30 | 31 | if (annotation == null) { 32 | continue; 33 | } 34 | 35 | executors.add(new PsiJavaExecutorNode(this, method)); 36 | } 37 | 38 | return executors; 39 | } 40 | 41 | @Override 42 | public boolean hasExecutors() { 43 | return Arrays.stream(psiClass.getMethods()) 44 | .anyMatch(method -> method.getAnnotation(Execute.class.getName()) != null); 45 | } 46 | 47 | @Override 48 | public PsiFile getFile() { 49 | return psiClass.getContainingFile(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/api/psijava/PsiJavaPermissionEntry.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.api.psijava; 2 | 3 | import com.intellij.psi.PsiElement; 4 | import dev.rollczi.litecommands.intellijplugin.api.PermissionEntry; 5 | import dev.rollczi.litecommands.intellijplugin.navigatable.NavigatableReference; 6 | 7 | class PsiJavaPermissionEntry implements PermissionEntry { 8 | 9 | private final String name; 10 | private final NavigatableReference navigatable; 11 | 12 | public PsiJavaPermissionEntry(String name, PsiElement source) { 13 | this.name = name; 14 | this.navigatable = NavigatableReference.ofPsiElement(() -> source); 15 | } 16 | 17 | @Override 18 | public String name() { 19 | return name; 20 | } 21 | 22 | @Override 23 | public NavigatableReference navigatable() { 24 | return navigatable; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/icon/LiteIcons.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.icon; 2 | 3 | import com.intellij.icons.AllIcons; 4 | import com.intellij.openapi.util.IconLoader; 5 | 6 | import javax.swing.*; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | public interface LiteIcons { 11 | 12 | Icon LOGO = loadIcon("/assets/icons/litecommandsLogo.svg"); 13 | 14 | interface Template { 15 | Icon Java = loadIcon("/assets/icons/litecommandsIcon_class.svg"); 16 | Icon JavaRoot = loadIcon("/assets/icons/litecommandsIcon_class_root.svg"); 17 | Icon Kotlin = loadIcon("/assets/icons/litecommandsIcon_kotlin_class.svg"); 18 | Icon KotlinRoot = loadIcon("/assets/icons/litecommandsIcon_kotlin_root_class.svg"); 19 | } 20 | 21 | Icon COMMAND_MARK_LINE = loadIcon("/assets/icons/expUi/applicationRemote.svg"); 22 | Icon COMMAND_STRUCTURE = loadIcon("/assets/icons/expUi/groupByModule.svg"); 23 | Icon COMMAND_ELEMENT = loadIcon("/assets/icons/expUi/inlayRenameInCommentsActive.svg"); 24 | Icon COMMAND_ELEMENT_ALIAS = loadIcon("/assets/icons/expUi/inlayRenameInComments.svg"); 25 | 26 | Icon PERMISSIONS = loadIcon("/assets/icons/expUi/columnGoldKey.svg"); 27 | Icon PERMISSION_ELEMENT = loadIcon("/assets/icons/expUi/mongoFieldGoldKey.svg"); 28 | 29 | Icon EXECUTORS = loadIcon("/assets/icons/expUi/ocdRunConfiguration.svg"); 30 | Icon EXECUTOR_ELEMENT = loadIcon("/assets/icons/expUi/runParatest.svg"); 31 | 32 | Icon BETA = AllIcons.General.Beta; 33 | Icon ELEMENT = AllIcons.General.ChevronRight; 34 | Icon ADD = AllIcons.General.Add; 35 | Icon EDIT = AllIcons.General.Inline_edit; 36 | 37 | private static Icon loadIcon(String path) { 38 | return IconLoader.getIcon(path, LiteIcons.class); 39 | } 40 | 41 | List list = Arrays.asList( 42 | 43 | // commands 44 | AllIcons.Actions.Run_anything, 45 | AllIcons.Nodes.Console, 46 | 47 | // argument 48 | AllIcons.Toolwindows.ToolWindowStructure, 49 | AllIcons.Toolwindows.ToolWindowChanges, 50 | AllIcons.Toolwindows.ToolWindowCommit, 51 | AllIcons.Nodes.IdeaModule, 52 | 53 | // general 54 | AllIcons.General.Beta, 55 | 56 | // sec 57 | AllIcons.General.RunWithCoverage, 58 | AllIcons.RunConfigurations.TrackCoverage, 59 | AllIcons.Ide.Readonly, 60 | AllIcons.Ide.Readwrite, 61 | 62 | // inspec 63 | AllIcons.General.InspectionsEye, 64 | 65 | // list 66 | AllIcons.General.ChevronRight, 67 | AllIcons.General.ChevronLeft, 68 | 69 | // docs 70 | AllIcons.General.ReaderMode 71 | ); 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inlay/InlayHintsConfigurable.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inlay; 2 | 3 | import com.intellij.codeInsight.hints.ChangeListener; 4 | import com.intellij.codeInsight.hints.ImmediateConfigurable; 5 | import dev.rollczi.litecommands.intellijplugin.settings.LiteSettingsBox; 6 | import javax.swing.JComponent; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | class InlayHintsConfigurable implements ImmediateConfigurable { 10 | 11 | public InlayHintsConfigurable() { 12 | } 13 | 14 | @NotNull 15 | @Override 16 | public JComponent createComponent(@NotNull ChangeListener changeListener) { 17 | return new LiteSettingsBox(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inlay/InlayHintsIconPresentation.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inlay; 2 | 3 | import com.intellij.codeInsight.hints.presentation.BasePresentation; 4 | import com.intellij.codeInsight.hints.presentation.InputHandler; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.openapi.editor.markup.TextAttributes; 7 | import com.intellij.openapi.ui.popup.JBPopupFactory; 8 | import com.intellij.psi.PsiElement; 9 | import com.intellij.psi.PsiType; 10 | import com.intellij.ui.awt.RelativePoint; 11 | import java.awt.AlphaComposite; 12 | import java.awt.Cursor; 13 | import java.awt.Graphics2D; 14 | import java.awt.Point; 15 | import java.awt.Rectangle; 16 | import java.awt.event.MouseEvent; 17 | import javax.swing.Icon; 18 | import org.jetbrains.annotations.NotNull; 19 | 20 | class InlayHintsIconPresentation extends BasePresentation implements InputHandler { 21 | 22 | private Icon icon; 23 | private final PsiType psiType; 24 | private final PsiElement element; 25 | private final Editor editor; 26 | 27 | public InlayHintsIconPresentation(Icon icon, PsiType psiType, PsiElement element, Editor editor) { 28 | this.icon = icon; 29 | this.psiType = psiType; 30 | this.element = element; 31 | this.editor = editor; 32 | } 33 | 34 | public void setIcon(Icon icon) { 35 | this.icon = icon; 36 | fireContentChanged(new Rectangle(getWidth(), getHeight())); 37 | } 38 | 39 | public Icon getIcon() { 40 | return this.icon; 41 | } 42 | 43 | @Override 44 | public int getWidth() { 45 | return icon.getIconWidth(); 46 | } 47 | 48 | @Override 49 | public int getHeight() { 50 | return icon.getIconHeight(); 51 | } 52 | 53 | @Override 54 | public void mouseClicked(@NotNull MouseEvent event, @NotNull Point translated) { 55 | if (event.getClickCount() == 0) { 56 | return; 57 | } 58 | 59 | JBPopupFactory.getInstance() 60 | .createListPopup(new InlayPopupNewActions(event.getPoint(), psiType, editor, element)) 61 | .show(new RelativePoint(event)); 62 | } 63 | 64 | @Override 65 | public void mouseExited() { 66 | editor.getContentComponent().setCursor(Cursor.getDefaultCursor()); 67 | } 68 | 69 | @Override 70 | public void mouseMoved(@NotNull MouseEvent event, @NotNull Point translated) { 71 | editor.getContentComponent().setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 72 | } 73 | 74 | @Override 75 | public void paint(Graphics2D g, TextAttributes attributes) { 76 | Graphics2D graphics = (Graphics2D) g.create(); 77 | graphics.setComposite(AlphaComposite.SrcAtop.derive(1.0f)); 78 | icon.paintIcon(editor.getComponent(), graphics, 0, 0); 79 | graphics.dispose(); 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return ""; 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inlay/InlayPopupNewActions.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inlay; 2 | 3 | import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector; 4 | import com.intellij.icons.AllIcons; 5 | import com.intellij.openapi.editor.Editor; 6 | import com.intellij.openapi.ui.popup.PopupStep; 7 | import com.intellij.openapi.ui.popup.util.BaseListPopupStep; 8 | import com.intellij.psi.PsiElement; 9 | import com.intellij.psi.PsiType; 10 | import dev.rollczi.litecommands.intellijplugin.settings.LiteCommandsConfigurable; 11 | import dev.rollczi.litecommands.intellijplugin.settings.LiteCommandsSettings; 12 | import dev.rollczi.litecommands.intellijplugin.usage.Usage; 13 | import dev.rollczi.litecommands.intellijplugin.usage.UsageService; 14 | import dev.rollczi.litecommands.intellijplugin.util.LiteTypeSearcher; 15 | import java.awt.Point; 16 | import javax.swing.Icon; 17 | import org.jetbrains.annotations.NotNull; 18 | import org.jetbrains.annotations.Nullable; 19 | 20 | class InlayPopupNewActions extends BaseListPopupStep { 21 | 22 | public InlayPopupNewActions(Point point, PsiType type, Editor editor, PsiElement element) { 23 | super("Actions for " + type.getPresentableText() + " Argument", 24 | new Action(AllIcons.Actions.FindBackward, "Find parser declarations", () -> { 25 | UsageService usageService = UsageService.getInstance(); 26 | usageService.show( 27 | "Parsers of " + type.getPresentableText() + " type", 28 | "Parsers declarations", 29 | editor, 30 | element, 31 | point, 32 | () -> LiteTypeSearcher.findParsersByType(element.getProject(), type).stream() 33 | .map(parser -> new Usage(parser, ReadWriteAccessDetector.Access.Read)) 34 | .toList() 35 | ); 36 | }), 37 | new Action(AllIcons.Actions.FindForward, "Find suggester declarations", () -> { 38 | UsageService usageService = UsageService.getInstance(); 39 | 40 | usageService.show( 41 | "Suggesters of " + type.getPresentableText() + " type", 42 | "Suggesters declarations", 43 | editor, 44 | element, 45 | point, 46 | () -> LiteTypeSearcher.findSuggestersByType(element.getProject(), type).stream() 47 | .map(parser -> new Usage(parser, ReadWriteAccessDetector.Access.Read)) 48 | .toList() 49 | ); 50 | }), 51 | new Action(AllIcons.Actions.Uninstall, "Hide argument hints", () -> { 52 | LiteCommandsConfigurable configurable = LiteCommandsConfigurable.createConfigurable(); 53 | LiteCommandsSettings edited = configurable.getEdited(); 54 | 55 | edited.showArgumentHints = false; 56 | configurable.apply(); 57 | }) 58 | ); 59 | } 60 | 61 | @Override 62 | public Icon getIconFor(Action action) { 63 | return action.icon; 64 | } 65 | 66 | @Override 67 | public @NotNull String getTextFor(Action value) { 68 | return value.name(); 69 | } 70 | 71 | @Override 72 | public @Nullable PopupStep onChosen(Action selectedValue, boolean finalChoice) { 73 | selectedValue.action().run(); 74 | return PopupStep.FINAL_CHOICE; 75 | } 76 | 77 | record Action(Icon icon, String name, Runnable action) {} 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inlay/LiteInlayHints.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inlay; 2 | 3 | import com.intellij.codeInsight.hints.ImmediateConfigurable; 4 | import com.intellij.codeInsight.hints.InlayHintsCollector; 5 | import com.intellij.codeInsight.hints.InlayHintsProvider; 6 | import com.intellij.codeInsight.hints.InlayHintsSink; 7 | import com.intellij.codeInsight.hints.SettingsKey; 8 | import com.intellij.openapi.editor.Editor; 9 | import com.intellij.psi.PsiClassOwner; 10 | import com.intellij.psi.PsiFile; 11 | import dev.rollczi.litecommands.intellijplugin.settings.LiteCommandsSettings; 12 | import org.jetbrains.annotations.Nls; 13 | import org.jetbrains.annotations.NotNull; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | @SuppressWarnings({"UnstableApiUsage"}) 17 | public class LiteInlayHints implements InlayHintsProvider { 18 | 19 | public static final String KEY = "litecommands.argument"; 20 | public static final String NAME = "LiteCommands argument"; 21 | 22 | @NotNull 23 | @Override 24 | public SettingsKey getKey() { 25 | return new SettingsKey<>(KEY); 26 | } 27 | 28 | @Nls(capitalization = Nls.Capitalization.Sentence) 29 | @NotNull 30 | @Override 31 | public String getName() { 32 | return NAME; 33 | } 34 | 35 | @Nullable 36 | @Override 37 | public String getPreviewText() { 38 | return NAME; 39 | } 40 | 41 | @NotNull 42 | @Override 43 | public ImmediateConfigurable createConfigurable(@NotNull LiteCommandsSettings settings) { 44 | return new InlayHintsConfigurable(); 45 | } 46 | 47 | @NotNull 48 | @Override 49 | public LiteCommandsSettings createSettings() { 50 | return LiteCommandsSettings.getInstance(); 51 | } 52 | 53 | @Nullable 54 | @Override 55 | public InlayHintsCollector getCollectorFor(@NotNull PsiFile psiFile, @NotNull Editor editor, @NotNull LiteCommandsSettings settings, @NotNull InlayHintsSink inlayHintsSink) { 56 | if (!(psiFile instanceof PsiClassOwner)) { 57 | return null; 58 | } 59 | 60 | if (!settings.showArgumentHints) { 61 | return null; 62 | } 63 | 64 | return new LiteInlayHintsCollector(); 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inlay/ref/ArgumentPsiReferenceProvider.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inlay.ref; 2 | 3 | import com.intellij.psi.PsiAnnotation; 4 | import com.intellij.psi.PsiAnnotationParameterList; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.psi.PsiLiteralExpression; 7 | import com.intellij.psi.PsiNameValuePair; 8 | import com.intellij.psi.PsiParameter; 9 | import com.intellij.psi.PsiReference; 10 | import com.intellij.psi.PsiReferenceProvider; 11 | import com.intellij.util.ProcessingContext; 12 | import dev.rollczi.litecommands.annotations.argument.Arg; 13 | import dev.rollczi.litecommands.intellijplugin.util.LiteTypeChecks; 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | class ArgumentPsiReferenceProvider extends PsiReferenceProvider { 17 | 18 | ArgumentPsiReferenceProvider() { 19 | } 20 | 21 | @Override 22 | public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { 23 | PsiLiteralExpression literal = (PsiLiteralExpression) element; 24 | 25 | if (!(literal.getValue() instanceof String)) { 26 | return PsiReference.EMPTY_ARRAY; 27 | } 28 | 29 | if (!(element.getParent() instanceof PsiNameValuePair nameValuePair)) { 30 | return PsiReference.EMPTY_ARRAY; 31 | } 32 | 33 | if (!(nameValuePair.getParent() instanceof PsiAnnotationParameterList annotationParameterList)) { 34 | return PsiReference.EMPTY_ARRAY; 35 | } 36 | 37 | if (!(annotationParameterList.getParent() instanceof PsiAnnotation annotation)) { 38 | return PsiReference.EMPTY_ARRAY; 39 | } 40 | 41 | if (!(annotation.getParent().getParent() instanceof PsiParameter parameter)) { 42 | return PsiReference.EMPTY_ARRAY; 43 | } 44 | 45 | if (LiteTypeChecks.isArgumentAnnotation(annotation)) { 46 | return new PsiReference[] { 47 | new SimpleReference(parameter.getType(), element, element.getTextRangeInParent()) 48 | }; 49 | } 50 | 51 | return PsiReference.EMPTY_ARRAY; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inlay/ref/LitePsiReferenceContributor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inlay.ref; 2 | 3 | import com.intellij.patterns.PlatformPatterns; 4 | import com.intellij.psi.PsiLiteralExpression; 5 | import com.intellij.psi.PsiReferenceContributor; 6 | import com.intellij.psi.PsiReferenceRegistrar; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class LitePsiReferenceContributor extends PsiReferenceContributor { 10 | 11 | @Override 12 | public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { 13 | registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiLiteralExpression.class), new ArgumentPsiReferenceProvider()); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inlay/ref/SimpleReference.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inlay.ref; 2 | 3 | import com.intellij.codeInsight.lookup.LookupElement; 4 | import com.intellij.codeInsight.lookup.LookupElementBuilder; 5 | import com.intellij.openapi.util.TextRange; 6 | import com.intellij.psi.PsiClass; 7 | import com.intellij.psi.PsiElement; 8 | import com.intellij.psi.PsiElementResolveResult; 9 | import com.intellij.psi.PsiPolyVariantReference; 10 | import com.intellij.psi.PsiReferenceBase; 11 | import com.intellij.psi.PsiType; 12 | import com.intellij.psi.ResolveResult; 13 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 14 | import dev.rollczi.litecommands.intellijplugin.util.LiteTypeSearcher; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import org.jetbrains.annotations.NotNull; 18 | import org.jetbrains.annotations.Nullable; 19 | 20 | final class SimpleReference extends PsiReferenceBase implements PsiPolyVariantReference { 21 | 22 | private final PsiElement element; 23 | private final PsiType type; 24 | 25 | SimpleReference(PsiType type, @NotNull PsiElement element, TextRange textRange) { 26 | super(element, textRange); 27 | this.type = type; 28 | this.element = element; 29 | } 30 | 31 | @Override 32 | public ResolveResult @NotNull [] multiResolve(boolean incompleteCode) { 33 | List results = new ArrayList<>(); 34 | for (PsiClass parser : LiteTypeSearcher.findParsersByType(element.getProject(), type)) { 35 | results.add(new PsiElementResolveResult(parser)); 36 | } 37 | 38 | return results.toArray(new ResolveResult[0]); 39 | } 40 | 41 | @Nullable 42 | @Override 43 | public PsiElement resolve() { 44 | ResolveResult[] resolveResults = multiResolve(false); 45 | return resolveResults.length == 1 ? resolveResults[0].getElement() : null; 46 | } 47 | 48 | @Override 49 | public Object @NotNull [] getVariants() { 50 | List variants = new ArrayList<>(); 51 | 52 | for (PsiClass parser : LiteTypeSearcher.findParsersByType(element.getProject(), type)) { 53 | variants.add(LookupElementBuilder 54 | .create(parser) 55 | .withIcon(LiteIcons.ADD) 56 | .withTypeText(parser.getContainingFile().getName()) 57 | ); 58 | } 59 | 60 | return variants.toArray(); 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/LiteInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection; 2 | 3 | import com.intellij.codeInspection.LocalInspectionTool; 4 | import org.jetbrains.annotations.Nls; 5 | import org.jetbrains.annotations.NotNull; 6 | 7 | public abstract class LiteInspection extends LocalInspectionTool { 8 | 9 | private final static String GROUP_NAME = "LiteCommands"; 10 | 11 | private final String displayName; 12 | 13 | public LiteInspection(String displayName) { 14 | this.displayName = displayName; 15 | } 16 | 17 | @Override 18 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getDisplayName() { 19 | return this.displayName; 20 | } 21 | 22 | @Override 23 | public @Nls(capitalization = Nls.Capitalization.Sentence) @NotNull String getGroupDisplayName() { 24 | return GROUP_NAME; 25 | } 26 | 27 | @Override 28 | public boolean isEnabledByDefault() { 29 | return true; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/LiteInspectionProvider.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection; 2 | 3 | import com.intellij.codeInspection.InspectionToolProvider; 4 | import dev.rollczi.litecommands.intellijplugin.inspection.executor.ExecutorNotAnnotatedParameterInspection; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy.LegacyArgInspection; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy.LegacyExecuteInspection; 7 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy.LegacyJoinInspection; 8 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy.LegacyPermissionInspection; 9 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy.LegacyRouteInspection; 10 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy.LegacySectionInspection; 11 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation.ExecuteValidationInspection; 12 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation.CommandValidationInspection; 13 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation.ShortcutValidationInspection; 14 | import dev.rollczi.litecommands.intellijplugin.inspection.parameter.LiteralAnnotationInspection; 15 | import dev.rollczi.litecommands.intellijplugin.inspection.parameter.ParameterMixedAnnotationsInspection; 16 | import dev.rollczi.litecommands.intellijplugin.inspection.parameter.ParameterNullableOptionalPrimitiveInspection; 17 | import dev.rollczi.litecommands.intellijplugin.inspection.parameter.ParameterNullableOptionalWrappedInspection; 18 | import dev.rollczi.litecommands.intellijplugin.inspection.parameter.VarargsAnnotationInspection; 19 | import org.jetbrains.annotations.NotNull; 20 | 21 | public class LiteInspectionProvider implements InspectionToolProvider { 22 | 23 | @Override 24 | public Class @NotNull [] getInspectionClasses() { 25 | return new Class[]{ 26 | ExecutorNotAnnotatedParameterInspection.class, 27 | ParameterNullableOptionalPrimitiveInspection.class, 28 | VarargsAnnotationInspection.class, 29 | LiteralAnnotationInspection.class, 30 | ParameterNullableOptionalWrappedInspection.class, 31 | ParameterMixedAnnotationsInspection.class, 32 | LegacyRouteInspection.class, 33 | LegacySectionInspection.class, 34 | LegacyArgInspection.class, 35 | LegacyExecuteInspection.class, 36 | LegacyJoinInspection.class, 37 | LegacyPermissionInspection.class, 38 | ExecuteValidationInspection.class, 39 | CommandValidationInspection.class, 40 | ShortcutValidationInspection.class 41 | }; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/annotation/LiteNullabilityAnnotationPackage.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.annotation; 2 | 3 | import com.intellij.codeInsight.Nullability; 4 | import com.intellij.codeInsight.NullabilityAnnotationInfo; 5 | import com.intellij.codeInsight.annoPackages.AnnotationPackageSupport; 6 | import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute; 7 | import com.intellij.lang.jvm.annotation.JvmAnnotationAttributeValue; 8 | import com.intellij.lang.jvm.annotation.JvmAnnotationConstantValue; 9 | import com.intellij.psi.PsiAnnotation; 10 | import com.intellij.psi.PsiElement; 11 | import dev.rollczi.litecommands.annotations.argument.Arg; 12 | import dev.rollczi.litecommands.annotations.flag.Flag; 13 | import dev.rollczi.litecommands.annotations.join.Join; 14 | import dev.rollczi.litecommands.annotations.literal.Literal; 15 | import dev.rollczi.litecommands.annotations.optional.OptionalArg; 16 | import dev.rollczi.litecommands.annotations.varargs.Varargs; 17 | import dev.rollczi.litecommands.intellijplugin.annotation.AnnotationFactory; 18 | import dev.rollczi.litecommands.intellijplugin.annotation.AnnotationHolder; 19 | import java.util.List; 20 | import java.util.Optional; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | 24 | public class LiteNullabilityAnnotationPackage implements AnnotationPackageSupport { 25 | 26 | @Override 27 | public @NotNull List getNullabilityAnnotations(@NotNull Nullability nullability) { 28 | return switch (nullability) { 29 | case NOT_NULL -> List.of( 30 | Join.class.getName(), 31 | Varargs.class.getName(), 32 | Literal.class.getName(), 33 | Flag.class.getName() 34 | ); 35 | case NULLABLE -> List.of( 36 | OptionalArg.class.getName() 37 | ); 38 | case UNKNOWN -> List.of(); 39 | }; 40 | } 41 | 42 | @Override 43 | public @Nullable NullabilityAnnotationInfo getNullabilityByContainerAnnotation(@NotNull PsiAnnotation anno, @NotNull PsiElement context, PsiAnnotation.TargetType @NotNull [] types, boolean superPackage) { 44 | if (!Arg.class.getName().equals(anno.getQualifiedName())) { 45 | return null; 46 | } 47 | 48 | @Nullable JvmAnnotationAttribute attribute = anno.findAttribute("nullable"); 49 | if (attribute == null) { 50 | return null; 51 | } 52 | 53 | @Nullable JvmAnnotationAttributeValue value = attribute.getAttributeValue(); 54 | if (!(value instanceof JvmAnnotationConstantValue constantValue)) { 55 | return null; 56 | } 57 | 58 | if (!(constantValue.getConstantValue() instanceof Boolean nullable)) { 59 | return null; 60 | } 61 | 62 | return new NullabilityAnnotationInfo(anno, nullable ? Nullability.NULLABLE : Nullability.NOT_NULL, false); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/executor/ExecutorNotAnnotatedParameterInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.executor; 2 | 3 | import com.intellij.codeInsight.intention.AddAnnotationFix; 4 | import com.intellij.codeInspection.LocalQuickFix; 5 | import com.intellij.codeInspection.ProblemHighlightType; 6 | import com.intellij.codeInspection.ProblemsHolder; 7 | import com.intellij.psi.*; 8 | import dev.rollczi.litecommands.annotations.argument.Arg; 9 | import dev.rollczi.litecommands.annotations.bind.Bind; 10 | import dev.rollczi.litecommands.annotations.context.Context; 11 | import dev.rollczi.litecommands.annotations.execute.Execute; 12 | import dev.rollczi.litecommands.intellijplugin.inspection.LiteInspection; 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | public class ExecutorNotAnnotatedParameterInspection extends LiteInspection { 16 | 17 | private static final String DISPLAY_NAME = "Executor parameter is not annotated with e.g. @Arg, @Context, @Bind"; 18 | private static final String PROBLEM_DESCRIPTION = "Missing @Arg or @Context annotation"; 19 | 20 | public ExecutorNotAnnotatedParameterInspection() { 21 | super(DISPLAY_NAME); 22 | } 23 | 24 | @Override 25 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { 26 | return new MethodVisitor(holder); 27 | } 28 | 29 | private static class MethodVisitor extends JavaElementVisitor { 30 | 31 | private final ProblemsHolder holder; 32 | 33 | public MethodVisitor(ProblemsHolder holder) { 34 | this.holder = holder; 35 | } 36 | 37 | @Override 38 | public void visitMethod(@NotNull PsiMethod method) { 39 | PsiAnnotation annotation = method.getAnnotation(Execute.class.getName()); 40 | 41 | if (annotation == null) { 42 | return; 43 | } 44 | 45 | PsiParameterList parameterList = method.getParameterList(); 46 | 47 | for (PsiParameter parameter : parameterList.getParameters()) { 48 | if (parameter.getAnnotations().length != 0) { 49 | continue; 50 | } 51 | 52 | holder.registerProblem(parameter, PROBLEM_DESCRIPTION, ProblemHighlightType.GENERIC_ERROR, fixes(parameter)); 53 | } 54 | } 55 | 56 | private LocalQuickFix[] fixes(PsiParameter par) { 57 | return new LocalQuickFix[] { 58 | new AddAnnotationFix(Arg.class.getName(), par), 59 | new AddAnnotationFix(Context.class.getName(), par), 60 | new AddAnnotationFix(Bind.class.getName(), par), 61 | }; 62 | } 63 | 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/AnnotationMapper.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public final class AnnotationMapper { 7 | 8 | private final String legacyName; 9 | private final String modernName; 10 | private final List attributes; 11 | 12 | private AnnotationMapper(String legacyName, String modernName, List attributes) { 13 | this.legacyName = legacyName; 14 | this.modernName = modernName; 15 | this.attributes = attributes; 16 | } 17 | 18 | public String legacyQualified() { 19 | return this.legacyName; 20 | } 21 | 22 | public String modernQualified() { 23 | return this.modernName; 24 | } 25 | 26 | public String legacyName() { 27 | return this.toShortName(this.legacyName); 28 | } 29 | 30 | public String modernName() { 31 | return this.toShortName(this.modernName); 32 | } 33 | 34 | public String legacyAnnotation() { 35 | return "@" + this.legacyName(); 36 | } 37 | 38 | public String modernAnnotation() { 39 | return "@" + this.modernName(); 40 | } 41 | 42 | private String toShortName(String name) { 43 | return name.substring(name.lastIndexOf('.') + 1); 44 | } 45 | 46 | public List getAttributes() { 47 | return this.attributes; 48 | } 49 | 50 | public static Builder builder() { 51 | return new Builder(); 52 | } 53 | 54 | public static class Builder { 55 | 56 | private String legacyName; 57 | private String modernName; 58 | private final List attributes = new ArrayList<>(); 59 | 60 | public Builder legacyName(String legacyName) { 61 | this.legacyName = legacyName; 62 | return this; 63 | } 64 | 65 | public Builder modernName(String modernName) { 66 | this.modernName = modernName; 67 | return this; 68 | } 69 | 70 | public Builder attribute(String legacy, String modern, AttributeType type) { 71 | this.attributes.add(new Attribute(legacy, modern, type)); 72 | return this; 73 | } 74 | 75 | public AnnotationMapper build() { 76 | return new AnnotationMapper(this.legacyName, this.modernName, this.attributes); 77 | } 78 | 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/AnnotationMapperAttributeSchema.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import java.util.function.Predicate; 4 | import java.util.function.UnaryOperator; 5 | 6 | class AnnotationMapperAttributeSchema { 7 | 8 | private final String name; 9 | private final AttributeType type; 10 | private final Predicate validator; 11 | private final UnaryOperator quickFix; 12 | 13 | public AnnotationMapperAttributeSchema(String name, AttributeType type, Predicate validator, UnaryOperator quickFix) { 14 | this.name = name; 15 | this.type = type; 16 | this.validator = validator; 17 | this.quickFix = quickFix; 18 | } 19 | 20 | public String name() { 21 | return this.name; 22 | } 23 | 24 | public AttributeType type() { 25 | return this.type; 26 | } 27 | 28 | public boolean validate(String value) { 29 | return this.validator.test(value); 30 | } 31 | 32 | public String quickFix(String value) { 33 | return this.quickFix.apply(value); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/AnnotationMapperSchema.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | import java.util.function.Predicate; 6 | import java.util.function.UnaryOperator; 7 | 8 | public final class AnnotationMapperSchema { 9 | 10 | private final String name; 11 | private final Set annotationMapperAttributeSchemas; 12 | 13 | private AnnotationMapperSchema(String name, Set annotationMapperAttributeSchemas) { 14 | this.name = name; 15 | this.annotationMapperAttributeSchemas = annotationMapperAttributeSchemas; 16 | } 17 | 18 | public String qualifiedName() { 19 | return this.name; 20 | } 21 | 22 | public String name() { 23 | return this.name.substring(this.name.lastIndexOf('.') + 1); 24 | } 25 | 26 | public String annotation() { 27 | return "@" + this.name(); 28 | } 29 | 30 | public Set getAttributesValidators() { 31 | return this.annotationMapperAttributeSchemas; 32 | } 33 | 34 | public static Builder builder() { 35 | return new Builder(); 36 | } 37 | 38 | public static class Builder { 39 | 40 | private String name; 41 | private final Set annotationMapperAttributeSchemas = new HashSet<>(); 42 | 43 | public Builder name(String name) { 44 | this.name = name; 45 | return this; 46 | } 47 | 48 | public Builder attribute(String modern, AttributeType type, Predicate validator, UnaryOperator quickFix) { 49 | this.annotationMapperAttributeSchemas.add(new AnnotationMapperAttributeSchema(modern, type, validator, quickFix)); 50 | return this; 51 | } 52 | 53 | public AnnotationMapperSchema build() { 54 | return new AnnotationMapperSchema(this.name, this.annotationMapperAttributeSchemas); 55 | } 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/AnnotationVisitor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import com.intellij.codeInspection.ProblemHighlightType; 4 | import com.intellij.codeInspection.ProblemsHolder; 5 | import com.intellij.psi.JavaElementVisitor; 6 | import com.intellij.psi.PsiAnnotation; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | class AnnotationVisitor extends JavaElementVisitor { 10 | 11 | private final String displayName; 12 | private final AnnotationMapper mapper; 13 | private final ProblemsHolder holder; 14 | 15 | AnnotationVisitor(String displayName, AnnotationMapper mapper, ProblemsHolder holder) { 16 | this.displayName = displayName; 17 | this.mapper = mapper; 18 | this.holder = holder; 19 | } 20 | 21 | @Override 22 | public void visitAnnotation(@NotNull PsiAnnotation annotation) { 23 | super.visitAnnotation(annotation); 24 | 25 | String qualifiedName = annotation.getQualifiedName(); 26 | 27 | if (qualifiedName == null) { 28 | return; 29 | } 30 | 31 | if (!qualifiedName.contains(".")) { 32 | if (this.mapper.legacyName().equals(qualifiedName)) { 33 | this.holder.registerProblem(annotation, this.displayName, ProblemHighlightType.GENERIC_ERROR, new AnnotationReplaceQuickFix(this.mapper, this.holder)); 34 | } 35 | 36 | return; 37 | } 38 | 39 | if (this.mapper.legacyQualified().equals(qualifiedName)) { 40 | this.holder.registerProblem(annotation, this.displayName, ProblemHighlightType.GENERIC_ERROR, new AnnotationReplaceQuickFix(this.mapper, this.holder)); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/Attribute.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | class Attribute { 4 | 5 | private final String legacyName; 6 | private final String modernName; 7 | private final AttributeType type; 8 | 9 | Attribute(String legacyName, String modernName, AttributeType type) { 10 | this.legacyName = legacyName; 11 | this.modernName = modernName; 12 | this.type = type; 13 | } 14 | 15 | AttributeType type() { 16 | return this.type; 17 | } 18 | 19 | String legacyName() { 20 | return this.legacyName; 21 | } 22 | 23 | String modernName() { 24 | return this.modernName; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/AttributeType.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import java.util.function.Predicate; 4 | 5 | public enum AttributeType { 6 | STRING, 7 | INT, 8 | LONG, 9 | FLOAT, 10 | DOUBLE, 11 | BOOLEAN, 12 | CHAR, 13 | BYTE, 14 | SHORT, 15 | CLASS, 16 | ENUM, 17 | ANNOTATION, 18 | ARRAY(value -> !value.equals("{}")); 19 | 20 | private final Predicate predicate; 21 | 22 | AttributeType() { 23 | this.predicate = value -> true; 24 | } 25 | 26 | AttributeType(Predicate predicate) { 27 | this.predicate = predicate; 28 | } 29 | 30 | public boolean matches(String value) { 31 | return this.predicate.test(value); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/AttributeValue.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import com.intellij.psi.PsiElement; 4 | 5 | class AttributeValue { 6 | 7 | private final String text; 8 | private final String rawText; 9 | private final PsiElement element; 10 | 11 | AttributeValue(String text, String rawText, PsiElement element) { 12 | this.text = text; 13 | this.rawText = rawText; 14 | this.element = element; 15 | } 16 | 17 | public String text() { 18 | return this.text; 19 | } 20 | 21 | public String rawText() { 22 | return this.rawText; 23 | } 24 | 25 | public PsiElement element() { 26 | return this.element; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/LegacyAnnotationInspectionTool.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import com.intellij.codeInspection.AbstractBaseJavaLocalInspectionTool; 4 | import com.intellij.codeInspection.ProblemsHolder; 5 | import com.intellij.psi.PsiElementVisitor; 6 | import org.jetbrains.annotations.NotNull; 7 | 8 | public abstract class LegacyAnnotationInspectionTool extends AbstractBaseJavaLocalInspectionTool { 9 | 10 | private static final String DISPLAY_NAME = "Usage of @%s is not recommended. Use @%s instead"; 11 | 12 | private final AnnotationMapper mapper; 13 | 14 | protected LegacyAnnotationInspectionTool(AnnotationMapper mapper) { 15 | this.mapper = mapper; 16 | } 17 | 18 | @Override 19 | public @NotNull String getDisplayName() { 20 | return String.format(DISPLAY_NAME, this.mapper.legacyName(), this.mapper.modernName()); 21 | } 22 | 23 | @Override 24 | public @NotNull String getGroupDisplayName() { 25 | return "LiteCommands"; 26 | } 27 | 28 | @Override 29 | public boolean isEnabledByDefault() { 30 | return true; 31 | } 32 | 33 | @Override 34 | public @NotNull PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { 35 | return new AnnotationVisitor(this.getDisplayName(), this.mapper, holder); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/ReplaceWithValidValueQuickFix.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper; 2 | 3 | import com.intellij.codeInspection.LocalQuickFix; 4 | import com.intellij.codeInspection.ProblemDescriptor; 5 | import com.intellij.codeInspection.util.IntentionFamilyName; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.JavaPsiFacade; 8 | import com.intellij.psi.PsiAnnotation; 9 | import com.intellij.psi.PsiElement; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | class ReplaceWithValidValueQuickFix implements LocalQuickFix { 13 | 14 | private final PsiAnnotation patternAnnotation; 15 | private final AnnotationMapperAttributeSchema validator; 16 | private final AttributeValue value; 17 | 18 | public ReplaceWithValidValueQuickFix(PsiAnnotation patternAnnotation, AnnotationMapperAttributeSchema validator, AttributeValue value) { 19 | this.patternAnnotation = patternAnnotation; 20 | this.validator = validator; 21 | this.value = value; 22 | } 23 | 24 | @Override 25 | public @IntentionFamilyName @NotNull String getFamilyName() { 26 | String quickFix = this.validator.quickFix(this.value.rawText()); 27 | 28 | if (quickFix.startsWith("\"") && quickFix.endsWith("\"")) { 29 | quickFix = quickFix.substring(1, quickFix.length() - 1); 30 | } 31 | 32 | return "Replace with '" + quickFix + "'"; 33 | } 34 | 35 | @Override 36 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { 37 | String quickFix = this.validator.quickFix(this.value.rawText()); 38 | PsiElement old = this.value.element(); 39 | String annotationText = this.patternAnnotation.getText(); 40 | 41 | int start = old.getTextRange().getStartOffset() - this.patternAnnotation.getTextRange().getStartOffset(); 42 | int end = old.getTextRange().getEndOffset() - this.patternAnnotation.getTextRange().getStartOffset(); 43 | 44 | String newAnnotationText = annotationText.substring(0, start) + quickFix + annotationText.substring(end); 45 | 46 | this.patternAnnotation.replace(JavaPsiFacade.getElementFactory(project).createAnnotationFromText( 47 | newAnnotationText, 48 | this.patternAnnotation 49 | )); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/legacy/LegacyArgInspection.java: -------------------------------------------------------------------------------- 1 | 2 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy; 3 | 4 | import dev.rollczi.litecommands.annotations.argument.Arg; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapper; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.LegacyAnnotationInspectionTool; 7 | 8 | public class LegacyArgInspection extends LegacyAnnotationInspectionTool { 9 | 10 | private static final AnnotationMapper MAPPER = AnnotationMapper.builder() 11 | .legacyName("dev.rollczi.litecommands.argument.Arg") 12 | .modernName(Arg.class.getName()) 13 | .build(); 14 | 15 | public LegacyArgInspection() { 16 | super(MAPPER); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/legacy/LegacyExecuteInspection.java: -------------------------------------------------------------------------------- 1 | 2 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy; 3 | 4 | import dev.rollczi.litecommands.annotations.execute.Execute; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapper; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AttributeType; 7 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.LegacyAnnotationInspectionTool; 8 | 9 | public class LegacyExecuteInspection extends LegacyAnnotationInspectionTool { 10 | 11 | private static final AnnotationMapper MAPPER = AnnotationMapper.builder() 12 | .legacyName("dev.rollczi.litecommands.command.execute.Execute") 13 | .modernName(Execute.class.getName()) 14 | .attribute("route", "name", AttributeType.STRING) 15 | .attribute("aliases", "aliases", AttributeType.ARRAY) 16 | .build(); 17 | 18 | public LegacyExecuteInspection() { 19 | super(MAPPER); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/legacy/LegacyJoinInspection.java: -------------------------------------------------------------------------------- 1 | 2 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy; 3 | 4 | import dev.rollczi.litecommands.annotations.join.Join; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapper; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.LegacyAnnotationInspectionTool; 7 | 8 | public class LegacyJoinInspection extends LegacyAnnotationInspectionTool { 9 | 10 | private static final AnnotationMapper MAPPER = AnnotationMapper.builder() 11 | .legacyName("dev.rollczi.litecommands.argument.joiner.Joiner") 12 | .modernName(Join.class.getName()) 13 | .build(); 14 | 15 | public LegacyJoinInspection() { 16 | super(MAPPER); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/legacy/LegacyPermissionInspection.java: -------------------------------------------------------------------------------- 1 | 2 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy; 3 | 4 | import dev.rollczi.litecommands.annotations.permission.Permission; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapper; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AttributeType; 7 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.LegacyAnnotationInspectionTool; 8 | 9 | public class LegacyPermissionInspection extends LegacyAnnotationInspectionTool { 10 | 11 | private static final AnnotationMapper MAPPER = AnnotationMapper.builder() 12 | .legacyName("dev.rollczi.litecommands.command.permission.Permission") 13 | .modernName(Permission.class.getName()) 14 | .attribute("value", "value", AttributeType.ARRAY) 15 | .build(); 16 | 17 | public LegacyPermissionInspection() { 18 | super(MAPPER); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/legacy/LegacyRouteInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy; 2 | 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapper; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AttributeType; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.LegacyAnnotationInspectionTool; 7 | 8 | public class LegacyRouteInspection extends LegacyAnnotationInspectionTool { 9 | 10 | private static final AnnotationMapper MAPPER = AnnotationMapper.builder() 11 | .legacyName("dev.rollczi.litecommands.command.route.Route") 12 | .modernName(Command.class.getName()) 13 | .attribute("name", "name", AttributeType.STRING) 14 | .attribute("aliases", "aliases", AttributeType.ARRAY) 15 | .build(); 16 | 17 | public LegacyRouteInspection() { 18 | super(MAPPER); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/legacy/LegacySectionInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.legacy; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapper; 4 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AttributeType; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.LegacyAnnotationInspectionTool; 6 | 7 | public class LegacySectionInspection extends LegacyAnnotationInspectionTool { 8 | 9 | private static final AnnotationMapper MAPPER = AnnotationMapper.builder() 10 | .legacyName("dev.rollczi.litecommands.command.section.Section") 11 | .modernName("dev.rollczi.litecommands.command.route.Route") 12 | .attribute("route", "name", AttributeType.STRING) 13 | .attribute("aliases", "aliases", AttributeType.ARRAY) 14 | .build(); 15 | 16 | public LegacySectionInspection() { 17 | super(MAPPER); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/validation/CommandNameValidUtils.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation; 2 | 3 | import dev.rollczi.litecommands.util.LiteCommandsUtil; 4 | 5 | final class CommandNameValidUtils { 6 | 7 | private CommandNameValidUtils() { 8 | } 9 | 10 | static boolean validateRoute(String value) { 11 | try { 12 | return LiteCommandsUtil.checkName(value); 13 | } 14 | catch (IllegalArgumentException exception) { 15 | return false; 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/validation/CommandValidationInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation; 2 | 3 | import com.intellij.codeInspection.ProblemHighlightType; 4 | import dev.rollczi.litecommands.annotations.command.Command; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AttributeType; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapperSchema; 7 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.ValidationAnnotationInspectionTool; 8 | 9 | public class CommandValidationInspection extends ValidationAnnotationInspectionTool { 10 | 11 | private static final AnnotationMapperSchema COMMAND_VALIDATOR = AnnotationMapperSchema.builder() 12 | .name(Command.class.getName()) 13 | .attribute("name", AttributeType.STRING, CommandNameValidUtils::validateRoute, new RouteQuickFix()) 14 | .attribute("aliases", AttributeType.ARRAY, CommandNameValidUtils::validateRoute, new RouteQuickFix()) 15 | .build(); 16 | 17 | public CommandValidationInspection() { 18 | super(COMMAND_VALIDATOR, ProblemHighlightType.GENERIC_ERROR); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/validation/ExecuteValidationInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation; 2 | 3 | import com.intellij.codeInspection.ProblemHighlightType; 4 | import dev.rollczi.litecommands.annotations.execute.Execute; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AttributeType; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapperSchema; 7 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.ValidationAnnotationInspectionTool; 8 | 9 | public class ExecuteValidationInspection extends ValidationAnnotationInspectionTool { 10 | 11 | private static final AnnotationMapperSchema ROUTE_VALIDATOR = AnnotationMapperSchema.builder() 12 | .name(Execute.class.getName()) 13 | .attribute("name", AttributeType.STRING, CommandNameValidUtils::validateRoute, new RouteQuickFix()) 14 | .attribute("aliases", AttributeType.ARRAY, CommandNameValidUtils::validateRoute, new RouteQuickFix()) 15 | .build(); 16 | 17 | public ExecuteValidationInspection() { 18 | super(ROUTE_VALIDATOR, ProblemHighlightType.GENERIC_ERROR); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/validation/RouteQuickFix.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation; 2 | 3 | import java.util.function.UnaryOperator; 4 | 5 | class RouteQuickFix implements UnaryOperator { 6 | 7 | @Override 8 | public String apply(String rawValue) { 9 | if (rawValue.startsWith("\"") && rawValue.endsWith("\"")) { 10 | rawValue = rawValue.substring(1, rawValue.length() - 1); 11 | } 12 | 13 | String value = rawValue 14 | .replaceAll(" +", " ") 15 | .trim(); 16 | 17 | if (value.isEmpty()) { 18 | value = "name"; 19 | } 20 | 21 | return "\"" + value + "\""; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/validation/ShortcutValidationInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation; 2 | 3 | import com.intellij.codeInspection.ProblemHighlightType; 4 | import dev.rollczi.litecommands.annotations.shortcut.Shortcut; 5 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AnnotationMapperSchema; 6 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.AttributeType; 7 | import dev.rollczi.litecommands.intellijplugin.inspection.mapper.ValidationAnnotationInspectionTool; 8 | 9 | public class ShortcutValidationInspection extends ValidationAnnotationInspectionTool { 10 | 11 | private static final AnnotationMapperSchema ROUTE_VALIDATOR = AnnotationMapperSchema.builder() 12 | .name(Shortcut.class.getName()) 13 | .attribute("value", AttributeType.ARRAY, CommandNameValidUtils::validateRoute, new RouteQuickFix()) 14 | .build(); 15 | 16 | public ShortcutValidationInspection() { 17 | super(ROUTE_VALIDATOR, ProblemHighlightType.GENERIC_ERROR); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/mapper/validation/SingleRouteQuickFix.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.mapper.validation; 2 | 3 | import java.util.function.UnaryOperator; 4 | 5 | class SingleRouteQuickFix implements UnaryOperator { 6 | 7 | @Override 8 | public String apply(String rawValue) { 9 | if (rawValue.startsWith("\"") && rawValue.endsWith("\"")) { 10 | rawValue = rawValue.substring(1, rawValue.length() - 1); 11 | } 12 | 13 | String value = rawValue 14 | .replaceAll(" +", "") 15 | .trim(); 16 | 17 | if (value.isEmpty()) { 18 | value = "name"; 19 | } 20 | 21 | return "\"" + value + "\""; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/parameter/LiteralAnnotationInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.parameter; 2 | 3 | import com.intellij.codeInspection.LocalQuickFix; 4 | import com.intellij.codeInspection.ProblemHighlightType; 5 | import com.intellij.codeInspection.ProblemsHolder; 6 | import com.intellij.psi.JavaElementVisitor; 7 | import com.intellij.psi.PsiAnnotation; 8 | import com.intellij.psi.PsiElementVisitor; 9 | import com.intellij.psi.PsiMethod; 10 | import com.intellij.psi.PsiParameter; 11 | import com.intellij.psi.PsiParameterList; 12 | import dev.rollczi.litecommands.annotations.execute.Execute; 13 | import dev.rollczi.litecommands.annotations.literal.Literal; 14 | import dev.rollczi.litecommands.intellijplugin.inspection.LiteInspection; 15 | import dev.rollczi.litecommands.intellijplugin.quickfix.ChangeParameterTypeQuickFix; 16 | import java.util.Set; 17 | import org.jetbrains.annotations.NotNull; 18 | 19 | public class LiteralAnnotationInspection extends LiteInspection { 20 | 21 | private static final Set SUPPORTED_TYPES = Set.of( 22 | String.class.getName(), 23 | Void.class.getName() 24 | ); 25 | 26 | private static final String DISPLAY_NAME = "@Literal support only String type"; 27 | private static final String PROBLEM_DESCRIPTION = "%s type is not supported by @Literal! Use a String instead."; 28 | 29 | public LiteralAnnotationInspection() { 30 | super(DISPLAY_NAME); 31 | } 32 | 33 | @Override 34 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { 35 | return new MethodVisitor(holder); 36 | } 37 | 38 | private static class MethodVisitor extends JavaElementVisitor { 39 | 40 | private final ProblemsHolder holder; 41 | 42 | public MethodVisitor(ProblemsHolder holder) { 43 | this.holder = holder; 44 | } 45 | 46 | @Override 47 | public void visitMethod(@NotNull PsiMethod method) { 48 | PsiAnnotation annotation = method.getAnnotation(Execute.class.getName()); 49 | 50 | if (annotation == null) { 51 | return; 52 | } 53 | 54 | PsiParameterList parameterList = method.getParameterList(); 55 | 56 | for (PsiParameter parameter : parameterList.getParameters()) { 57 | PsiAnnotation[] annotations = parameter.getAnnotations(); 58 | 59 | for (PsiAnnotation psiAnnotation : annotations) { 60 | if (Literal.class.getName().equals(psiAnnotation.getQualifiedName())) { 61 | this.checkLiteralAnnotation(parameter); 62 | } 63 | } 64 | } 65 | } 66 | 67 | private void checkLiteralAnnotation(PsiParameter parameter) { 68 | if (SUPPORTED_TYPES.contains(parameter.getType().getCanonicalText())) { 69 | return; 70 | } 71 | 72 | String problemMessage = String.format(PROBLEM_DESCRIPTION, parameter.getType().getCanonicalText()); 73 | 74 | holder.registerProblem(parameter, problemMessage, ProblemHighlightType.GENERIC_ERROR, fixes(parameter)); 75 | } 76 | 77 | private LocalQuickFix[] fixes(PsiParameter parameter) { 78 | return new LocalQuickFix[] { new ChangeParameterTypeQuickFix(type -> "Replace to String", parameter, old -> "String") }; 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/inspection/parameter/ParameterNullableOptionalPrimitiveInspection.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.inspection.parameter; 2 | 3 | import com.intellij.codeInspection.LocalQuickFix; 4 | import com.intellij.codeInspection.ProblemHighlightType; 5 | import com.intellij.codeInspection.ProblemsHolder; 6 | import com.intellij.lang.jvm.types.JvmPrimitiveTypeKind; 7 | import com.intellij.openapi.editor.Document; 8 | import com.intellij.openapi.editor.RangeMarker; 9 | import com.intellij.psi.JavaElementVisitor; 10 | import com.intellij.psi.PsiAnnotation; 11 | import com.intellij.psi.PsiElementVisitor; 12 | import com.intellij.psi.PsiMethod; 13 | import com.intellij.psi.PsiParameter; 14 | import com.intellij.psi.PsiParameterList; 15 | import com.intellij.psi.PsiType; 16 | import dev.rollczi.litecommands.annotations.execute.Execute; 17 | import dev.rollczi.litecommands.annotations.optional.OptionalArg; 18 | import dev.rollczi.litecommands.intellijplugin.inspection.LiteInspection; 19 | import dev.rollczi.litecommands.intellijplugin.quickfix.ReplaceQuickFix; 20 | import org.jetbrains.annotations.NotNull; 21 | 22 | public class ParameterNullableOptionalPrimitiveInspection extends LiteInspection { 23 | 24 | private static final String DISPLAY_NAME = "Optional nullable parameter cannot be primitive"; 25 | private static final String PROBLEM_DESCRIPTION = "Optional nullable parameter cannot be primitive"; 26 | 27 | public ParameterNullableOptionalPrimitiveInspection() { 28 | super(DISPLAY_NAME); 29 | } 30 | 31 | @Override 32 | public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { 33 | return new MethodVisitor(holder); 34 | } 35 | 36 | private static class MethodVisitor extends JavaElementVisitor { 37 | 38 | private final ProblemsHolder holder; 39 | 40 | public MethodVisitor(ProblemsHolder holder) { 41 | this.holder = holder; 42 | } 43 | 44 | @Override 45 | public void visitMethod(@NotNull PsiMethod method) { 46 | PsiAnnotation annotation = method.getAnnotation(Execute.class.getName()); 47 | 48 | if (annotation == null) { 49 | return; 50 | } 51 | 52 | PsiParameterList parameterList = method.getParameterList(); 53 | 54 | for (PsiParameter parameter : parameterList.getParameters()) { 55 | if (parameter.getAnnotation(OptionalArg.class.getName()) == null) { 56 | continue; 57 | } 58 | 59 | PsiType type = parameter.getType(); 60 | JvmPrimitiveTypeKind primitiveKind = JvmPrimitiveTypeKind.getKindByName(type.getCanonicalText()); 61 | 62 | if (primitiveKind != null) { 63 | holder.registerProblem(parameter, PROBLEM_DESCRIPTION, ProblemHighlightType.GENERIC_ERROR, fixes(parameter, primitiveKind)); 64 | } 65 | } 66 | } 67 | 68 | private LocalQuickFix[] fixes(PsiParameter par, JvmPrimitiveTypeKind primitiveKind) { 69 | Document document = par.getContainingFile().getViewProvider().getDocument(); 70 | RangeMarker rangeMarker = document.createRangeMarker(par.getTypeElement().getTextRange()); 71 | String boxedType = primitiveKind.getBoxedFqn().substring(primitiveKind.getBoxedFqn().lastIndexOf(".") + 1); 72 | 73 | return new LocalQuickFix[] { 74 | new ReplaceQuickFix( 75 | "Replace primitive '" + primitiveKind.getName() + "' with boxed type '" + boxedType + "'", 76 | rangeMarker, 77 | boxedType 78 | ) 79 | }; 80 | } 81 | 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/LiteLineMarkerDescriptor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker; 2 | 3 | import com.intellij.codeInsight.daemon.LineMarkerProviderDescriptor; 4 | 5 | public abstract class LiteLineMarkerDescriptor extends LineMarkerProviderDescriptor { 6 | 7 | private final static String NAME = "LiteCommands"; 8 | 9 | @Override 10 | public final String getName() { 11 | return NAME; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/LiteLineMarkerInfo.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker; 2 | 3 | import com.intellij.codeInsight.daemon.LineMarkerInfo; 4 | import com.intellij.openapi.editor.markup.GutterIconRenderer.Alignment; 5 | import com.intellij.pom.Navigatable; 6 | import com.intellij.psi.PsiElement; 7 | import dev.rollczi.litecommands.LiteCommandsVariables; 8 | import dev.rollczi.litecommands.intellijplugin.popup.LitePopupFactory; 9 | 10 | import javax.swing.*; 11 | 12 | public class LiteLineMarkerInfo extends LineMarkerInfo { 13 | public LiteLineMarkerInfo(String name, String footer, T element, Icon icon, Icon titleIcon, JComponent component) { 14 | super( 15 | element, 16 | element.getTextRange(), 17 | icon, 18 | (psi) -> "Click to open " + name, 19 | (mouseEvent, elt) -> { 20 | LitePopupFactory.showPopup(name, footer, titleIcon, component, mouseEvent); 21 | }, 22 | Alignment.RIGHT, 23 | () -> name 24 | ); 25 | } 26 | 27 | public static Builder builder(E psiElement) { 28 | return new Builder<>(psiElement); 29 | } 30 | 31 | public static class Builder { 32 | 33 | private final E psiElement; 34 | 35 | private String name; 36 | private String footer = "LiteCommands " + LiteCommandsVariables.VERSION + " (" + LiteCommandsVariables.COMMIT.substring(0, 7) + ")"; 37 | private JComponent component; 38 | private Icon icon; 39 | private Icon viewIcon; 40 | 41 | public Builder(E psiElement) { 42 | this.psiElement = psiElement; 43 | } 44 | 45 | public Builder name(String name) { 46 | this.name = name; 47 | return this; 48 | } 49 | 50 | public Builder footer(String footer) { 51 | this.footer = footer; 52 | return this; 53 | } 54 | 55 | public Builder component(JComponent component) { 56 | this.component = component; 57 | return this; 58 | } 59 | 60 | public Builder lineIcon(Icon icon) { 61 | this.icon = icon; 62 | return this; 63 | } 64 | 65 | public Builder viewIcon(Icon viewIcon) { 66 | this.viewIcon = viewIcon; 67 | return this; 68 | } 69 | 70 | public LiteLineMarkerInfo build() { 71 | return new LiteLineMarkerInfo<>(name, footer, psiElement, icon, viewIcon, component); 72 | } 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/AddButton.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 4 | import dev.rollczi.litecommands.intellijplugin.ui.LiteActionBadge; 5 | import dev.rollczi.litecommands.intellijplugin.ui.LiteColors; 6 | import dev.rollczi.litecommands.intellijplugin.ui.LiteMargin; 7 | 8 | class AddButton extends LiteMargin { 9 | 10 | AddButton() { 11 | super(LiteMargin.TINY); 12 | 13 | LiteActionBadge badge = new LiteActionBadge( 14 | "", 15 | LiteColors.GRAY, 16 | LiteColors.GRAY_LIGHT, 17 | LiteIcons.ADD, 18 | LiteMargin.SMALL 19 | ); 20 | 21 | this.add(badge); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/CommandComponent.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command; 2 | 3 | import com.intellij.ui.components.JBBox; 4 | import dev.rollczi.litecommands.intellijplugin.api.CommandNode; 5 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 6 | import dev.rollczi.litecommands.intellijplugin.navigatable.NavigatableReference; 7 | import dev.rollczi.litecommands.intellijplugin.ui.*; 8 | 9 | import javax.swing.*; 10 | import java.awt.*; 11 | 12 | class CommandComponent extends JPanel { 13 | 14 | CommandComponent(CommandNode command) { 15 | super(new BorderLayout()); 16 | this.add(title(), BorderLayout.NORTH); 17 | this.add(content(command), BorderLayout.CENTER); 18 | } 19 | 20 | private JComponent title() { 21 | return new LiteTitledSeparator(LiteIcons.COMMAND_STRUCTURE, "Command Structure"); 22 | } 23 | 24 | private JComponent content(CommandNode command) { 25 | JPanel content = new JPanel(new BorderLayout()); 26 | content.add(list(command), BorderLayout.WEST); 27 | content.add(new EditButton(command), BorderLayout.EAST); 28 | 29 | return content; 30 | } 31 | 32 | private JComponent list(CommandNode command) { 33 | JBBox box = new JBBox(BoxLayout.Y_AXIS); 34 | box.setAlignmentX(JComponent.LEFT_ALIGNMENT); 35 | 36 | box.add(createBadge(command.name(), false, command.navigateToName())); 37 | 38 | for (String alias : command.aliases()) { 39 | box.add(createBadge(alias, true, command.navigateToAlias(alias))); 40 | } 41 | 42 | return box; 43 | } 44 | 45 | private JComponent createBadge(String name, boolean isAlias, NavigatableReference source) { 46 | LiteActionBadge badge = new LiteActionBadge( 47 | "/" + name + " ...", 48 | LiteColors.GRAY, 49 | LiteColors.GRAY_LIGHT, 50 | isAlias ? LiteIcons.COMMAND_ELEMENT_ALIAS : LiteIcons.COMMAND_ELEMENT, 51 | LiteMargin.SMALL 52 | ); 53 | 54 | badge.addListener((event) -> source.highlight()); 55 | 56 | return LiteBox.invisible(badge).margined(LiteMargin.TINY); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/CommandMarker.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command; 2 | 3 | import com.intellij.codeInsight.daemon.LineMarkerInfo; 4 | import com.intellij.psi.PsiAnnotation; 5 | import com.intellij.psi.PsiClass; 6 | import com.intellij.psi.PsiElement; 7 | import com.intellij.ui.components.JBBox; 8 | import dev.rollczi.litecommands.annotations.command.Command; 9 | import dev.rollczi.litecommands.intellijplugin.api.CommandNode; 10 | import dev.rollczi.litecommands.intellijplugin.api.psijava.PsiJavaCommandNode; 11 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 12 | import dev.rollczi.litecommands.intellijplugin.marker.LiteLineMarkerDescriptor; 13 | import dev.rollczi.litecommands.intellijplugin.marker.LiteLineMarkerInfo; 14 | import javax.swing.BorderFactory; 15 | import javax.swing.BoxLayout; 16 | import javax.swing.JComponent; 17 | import kotlin.Pair; 18 | import org.jetbrains.annotations.NotNull; 19 | import org.jetbrains.annotations.Nullable; 20 | import org.jetbrains.uast.UClass; 21 | import org.jetbrains.uast.UElement; 22 | import org.jetbrains.uast.UElementKt; 23 | import org.jetbrains.uast.UastUtils; 24 | 25 | public class CommandMarker extends LiteLineMarkerDescriptor { 26 | 27 | @Override 28 | public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { 29 | Pair pair = findCommandNode(element); 30 | 31 | if (pair == null) { 32 | return null; 33 | } 34 | 35 | CommandNode commandNode = pair.getFirst(); 36 | 37 | JBBox box = new JBBox(BoxLayout.Y_AXIS); 38 | box.setAlignmentX(JComponent.LEFT_ALIGNMENT); 39 | box.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); 40 | 41 | box.add(new CommandComponent(commandNode)); 42 | box.add(new PermissionsComponent(commandNode)); 43 | box.add(new ExecutorsComponent(commandNode)); 44 | 45 | return LiteLineMarkerInfo.builder(pair.getSecond()) 46 | .name("Command base viewer") 47 | .viewIcon(LiteIcons.BETA) 48 | .lineIcon(LiteIcons.COMMAND_MARK_LINE) 49 | .component(box) 50 | .build(); 51 | } 52 | 53 | @Nullable 54 | private static Pair findCommandNode(@NotNull PsiElement element) { 55 | UElement uElement = UastUtils.getUParentForIdentifier(element); 56 | 57 | if (!(uElement instanceof UClass uClass)) { 58 | return null; 59 | } 60 | 61 | PsiElement identifier = UElementKt.getSourcePsiElement(uClass.getUastAnchor()); 62 | 63 | if (identifier == null) { 64 | return null; 65 | } 66 | 67 | PsiClass javaPsi = uClass.getJavaPsi(); 68 | PsiAnnotation commandAnnotation = javaPsi.getAnnotation(Command.class.getName()); 69 | 70 | if (commandAnnotation == null) { 71 | return null; 72 | } 73 | 74 | return new Pair<>(new PsiJavaCommandNode(javaPsi), identifier); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/EditButton.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import dev.rollczi.litecommands.intellijplugin.api.CommandNode; 5 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 6 | import dev.rollczi.litecommands.intellijplugin.marker.command.dialog.EditDialog; 7 | import dev.rollczi.litecommands.intellijplugin.ui.LiteActionBadge; 8 | import dev.rollczi.litecommands.intellijplugin.ui.LiteColors; 9 | import dev.rollczi.litecommands.intellijplugin.ui.LiteMargin; 10 | import dev.rollczi.litecommands.intellijplugin.popup.LitePopupFactory; 11 | import dev.rollczi.litecommands.intellijplugin.util.IdeaTask; 12 | import dev.rollczi.litecommands.intellijplugin.util.IdeaTaskType; 13 | import javax.swing.JPanel; 14 | 15 | class EditButton extends LiteMargin { 16 | 17 | EditButton(CommandNode command) { 18 | super(LiteMargin.TINY); 19 | 20 | LiteActionBadge badge = new LiteActionBadge( 21 | LiteColors.GRAY, 22 | LiteColors.GRAY_LIGHT, 23 | LiteIcons.EDIT, 24 | LiteMargin.SMALL 25 | ); 26 | 27 | badge.addListener(event -> { 28 | LitePopupFactory.showPopup( 29 | "Loading...", 30 | "Waiting for indexing...", 31 | LiteIcons.COMMAND_ELEMENT, 32 | new JPanel(), 33 | event 34 | ); 35 | 36 | Project project = command.getFile().getProject(); 37 | 38 | IdeaTask.startInSmart(project) 39 | .then(() -> LitePopupFactory.closePopups()) 40 | .flatMap(() -> EditDialog.create(command)) 41 | .filter(IdeaTaskType.UI, editDialog -> editDialog.showAndGet()) 42 | .then(IdeaTaskType.writeCommand(project), dialog -> { 43 | command.name(dialog.getName()); 44 | command.aliases(dialog.getAliases()); 45 | command.permissionsDefinition().permissions(dialog.getPermissions()); 46 | }); 47 | }); 48 | 49 | this.add(badge); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/ExecutorsComponent.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.api.CommandNode; 4 | import dev.rollczi.litecommands.intellijplugin.api.ExecutorNode; 5 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 6 | import dev.rollczi.litecommands.intellijplugin.marker.ui.ExecutorBadgeFactory; 7 | import dev.rollczi.litecommands.intellijplugin.ui.*; 8 | 9 | import javax.swing.*; 10 | import java.awt.*; 11 | 12 | class ExecutorsComponent extends JPanel { 13 | 14 | public ExecutorsComponent(CommandNode command) { 15 | super(new BorderLayout()); 16 | 17 | if (!command.hasExecutors()) { 18 | this.setVisible(false); 19 | return; 20 | } 21 | 22 | this.add(this.title(), BorderLayout.NORTH); 23 | this.add(this.content(command), BorderLayout.CENTER); 24 | } 25 | 26 | private JComponent title() { 27 | return new LiteTitledSeparator(LiteIcons.EXECUTORS, "Executors"); 28 | } 29 | 30 | private JComponent content(CommandNode command) { 31 | JPanel content = new JPanel(new BorderLayout()); 32 | content.add(commandList(command), BorderLayout.WEST); 33 | // content.add(new AddButton(), BorderLayout.EAST); TODO: add dialog for adding new executor 34 | 35 | return content; 36 | } 37 | 38 | private JComponent commandList(CommandNode command) { 39 | LiteBox box = new LiteBox(LiteColors.NONE); 40 | 41 | for (ExecutorNode executor : command.executors()) { 42 | box.with(ExecutorBadgeFactory.create(executor, this)); 43 | } 44 | 45 | return box; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/PermissionsComponent.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.api.CommandNode; 4 | import dev.rollczi.litecommands.intellijplugin.api.PermissionEntry; 5 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 6 | import dev.rollczi.litecommands.intellijplugin.ui.LiteActionBadge; 7 | import dev.rollczi.litecommands.intellijplugin.ui.LiteBox; 8 | import dev.rollczi.litecommands.intellijplugin.ui.LiteColors; 9 | import dev.rollczi.litecommands.intellijplugin.ui.LiteComponent; 10 | import dev.rollczi.litecommands.intellijplugin.ui.LiteMargin; 11 | import dev.rollczi.litecommands.intellijplugin.ui.LiteTitledSeparator; 12 | import java.awt.BorderLayout; 13 | import javax.swing.JComponent; 14 | import javax.swing.JPanel; 15 | 16 | class PermissionsComponent extends JPanel { 17 | 18 | PermissionsComponent(CommandNode command) { 19 | super(new BorderLayout()); 20 | 21 | this.add(this.title(), BorderLayout.NORTH); 22 | this.add(this.content(command), BorderLayout.CENTER); 23 | } 24 | 25 | private JComponent title() { 26 | return new LiteTitledSeparator(LiteIcons.PERMISSIONS, "Permissions"); 27 | } 28 | 29 | private JComponent content(CommandNode command) { 30 | JPanel content = new JPanel(new BorderLayout()); 31 | content.add(permissionsList(command), BorderLayout.WEST); 32 | content.add(new EditButton(command), BorderLayout.EAST); 33 | 34 | return content; 35 | } 36 | 37 | private JComponent permissionsList(CommandNode command) { 38 | LiteBox box = new LiteBox(LiteColors.NONE); 39 | 40 | for (PermissionEntry permissionEntry : command.permissionsDefinition().permissions()) { 41 | box.with(permissionBadge(permissionEntry)); 42 | } 43 | 44 | return box; 45 | } 46 | 47 | private LiteComponent permissionBadge(PermissionEntry permissionEntry) { 48 | LiteActionBadge badge = new LiteActionBadge( 49 | permissionEntry.name(), 50 | LiteColors.GRAY, 51 | LiteColors.GRAY_LIGHT, 52 | LiteIcons.PERMISSION_ELEMENT, 53 | LiteMargin.SMALL 54 | ); 55 | 56 | badge.addListener((event) -> permissionEntry.navigatable().highlight()); 57 | 58 | return LiteBox.invisible(badge).margined(LiteMargin.TINY); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/dialog/EditDialog.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command.dialog; 2 | 3 | import com.intellij.openapi.ui.DialogWrapper; 4 | import com.intellij.openapi.ui.ValidationInfo; 5 | import com.intellij.util.ui.ListTableModel; 6 | import dev.rollczi.litecommands.intellijplugin.api.CommandNode; 7 | import dev.rollczi.litecommands.intellijplugin.util.IdeaTask; 8 | import dev.rollczi.litecommands.util.LiteCommandsUtil; 9 | import java.util.List; 10 | import javax.swing.JComponent; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | public class EditDialog extends DialogWrapper { 14 | 15 | private EditDialogPanel panel; 16 | 17 | public EditDialog() { 18 | super(true); 19 | this.setTitle("Edit Command"); 20 | 21 | this.setOKButtonText("Edit"); 22 | this.setCancelButtonText("Cancel"); 23 | this.setOKActionEnabled(true); 24 | this.setResizable(true); 25 | } 26 | 27 | public static IdeaTask create(CommandNode command) { 28 | EditDialog dialog = new EditDialog(); 29 | 30 | return EditDialogPanel.create(command).ui(dialogPanel -> { 31 | dialog.panel = dialogPanel; 32 | dialog.init(); 33 | return dialog; 34 | }); 35 | } 36 | 37 | @Override 38 | protected @Nullable JComponent createCenterPanel() { 39 | return panel; 40 | } 41 | 42 | @Override 43 | protected @Nullable ValidationInfo doValidate() { 44 | ListTableModel model = panel.getNamesList().getListTableModel(); 45 | 46 | if (model.getItems().isEmpty()) { 47 | return new ValidationInfo("There must be at least one name", panel.getNamesList()); 48 | } 49 | 50 | for (TextReference item : model.getItems()) { 51 | try { 52 | boolean isNotEmpty = LiteCommandsUtil.checkName(item.getName()); 53 | 54 | if (isNotEmpty) { 55 | continue; 56 | } 57 | 58 | return new ValidationInfo("Command name cannot be empty", panel.getNamesList()); 59 | } 60 | catch (IllegalArgumentException exception) { 61 | return new ValidationInfo(exception.getMessage(), panel.getNamesList()); 62 | } 63 | } 64 | 65 | return null; 66 | } 67 | 68 | public String getName() { 69 | return panel.getNamesList().getListTableModel().getItems().get(0).getName(); 70 | } 71 | 72 | public List getAliases() { 73 | return panel.getNamesList().getListTableModel().getItems().stream() 74 | .skip(1) 75 | .map(TextReference::getName) 76 | .toList(); 77 | } 78 | 79 | public List getPermissions() { 80 | return panel.getPermissionsList().getListTableModel().getItems().stream() 81 | .map(TextReference::getName) 82 | .toList(); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/command/dialog/TextReference.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.command.dialog; 2 | 3 | class TextReference { 4 | private String name; 5 | 6 | public TextReference(String name) { 7 | this.name = name; 8 | } 9 | 10 | public String getName() { 11 | return name; 12 | } 13 | 14 | public void setName(String name) { 15 | this.name = name; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/executor/ExecutorComponent.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.executor; 2 | 3 | import dev.rollczi.litecommands.intellijplugin.api.ExecutorNode; 4 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 5 | import dev.rollczi.litecommands.intellijplugin.marker.ui.ExecutorBadgeFactory; 6 | import dev.rollczi.litecommands.intellijplugin.ui.LiteBox; 7 | import dev.rollczi.litecommands.intellijplugin.ui.LiteColors; 8 | import dev.rollczi.litecommands.intellijplugin.ui.LiteTitledSeparator; 9 | import java.awt.BorderLayout; 10 | import javax.swing.JComponent; 11 | import javax.swing.JPanel; 12 | 13 | class ExecutorComponent extends JPanel { 14 | 15 | public ExecutorComponent(ExecutorNode executorNode) { 16 | super(new BorderLayout()); 17 | this.add(this.title(), BorderLayout.NORTH); 18 | this.add(this.content(executorNode), BorderLayout.CENTER); 19 | } 20 | 21 | private JComponent title() { 22 | return new LiteTitledSeparator(LiteIcons.EXECUTORS, "Executor structure"); 23 | } 24 | 25 | private JComponent content(ExecutorNode command) { 26 | JPanel content = new JPanel(new BorderLayout()); 27 | content.add(commandList(command), BorderLayout.WEST); 28 | // content.add(new AddButton(), BorderLayout.EAST); TODO: add dialog for adding new executor 29 | 30 | return content; 31 | } 32 | 33 | private JComponent commandList(ExecutorNode executorNode) { 34 | LiteBox box = new LiteBox(LiteColors.NONE); 35 | 36 | box.with(ExecutorBadgeFactory.create(executorNode, this)); 37 | 38 | return box; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/executor/ExecutorMarker.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.executor; 2 | 3 | import com.intellij.codeInsight.daemon.LineMarkerInfo; 4 | import com.intellij.psi.PsiAnnotation; 5 | import com.intellij.psi.PsiClass; 6 | import com.intellij.psi.PsiElement; 7 | import com.intellij.psi.PsiMethod; 8 | import com.intellij.ui.components.JBBox; 9 | import dev.rollczi.litecommands.annotations.command.Command; 10 | import dev.rollczi.litecommands.annotations.execute.Execute; 11 | import dev.rollczi.litecommands.intellijplugin.api.ExecutorNode; 12 | import dev.rollczi.litecommands.intellijplugin.api.psijava.PsiJavaCommandNode; 13 | import dev.rollczi.litecommands.intellijplugin.api.psijava.PsiJavaExecutorNode; 14 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 15 | import dev.rollczi.litecommands.intellijplugin.marker.LiteLineMarkerDescriptor; 16 | import dev.rollczi.litecommands.intellijplugin.marker.LiteLineMarkerInfo; 17 | import javax.swing.BorderFactory; 18 | import javax.swing.BoxLayout; 19 | import javax.swing.JComponent; 20 | import kotlin.Pair; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.uast.UElement; 23 | import org.jetbrains.uast.UElementKt; 24 | import org.jetbrains.uast.UMethod; 25 | import org.jetbrains.uast.UastUtils; 26 | 27 | public class ExecutorMarker extends LiteLineMarkerDescriptor { 28 | 29 | @Override 30 | public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { 31 | Pair pair = findCommandNode(element); 32 | 33 | if (pair == null) { 34 | return null; 35 | } 36 | 37 | ExecutorNode executorNode = pair.getFirst(); 38 | 39 | JBBox box = new JBBox(BoxLayout.Y_AXIS); 40 | box.setAlignmentX(JComponent.LEFT_ALIGNMENT); 41 | box.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); 42 | 43 | box.add(new ExecutorComponent(executorNode)); 44 | 45 | return LiteLineMarkerInfo.builder(pair.getSecond()) 46 | .name("Command executor viewer") 47 | .viewIcon(LiteIcons.BETA) 48 | .lineIcon(LiteIcons.EXECUTORS) 49 | .component(box) 50 | .build(); 51 | } 52 | 53 | private static Pair findCommandNode(@NotNull PsiElement element) { 54 | UElement uElement = UastUtils.getUParentForIdentifier(element); 55 | 56 | if (!(uElement instanceof UMethod uMethod)) { 57 | return null; 58 | } 59 | 60 | PsiElement identifier = UElementKt.getSourcePsiElement(uMethod.getUastAnchor()); 61 | 62 | if (identifier == null) { 63 | return null; 64 | } 65 | 66 | PsiMethod psiMethod = uMethod.getJavaPsi(); 67 | PsiAnnotation commandAnnotation = psiMethod.getAnnotation(Execute.class.getName()); 68 | 69 | if (commandAnnotation == null) { 70 | return null; 71 | } 72 | 73 | PsiClass aClass = psiMethod.getContainingClass(); 74 | 75 | if (aClass == null) { 76 | return null; 77 | } 78 | 79 | PsiAnnotation command = aClass.getAnnotation(Command.class.getName()); 80 | 81 | if (command == null) { 82 | return null; 83 | } 84 | 85 | PsiJavaCommandNode commandNode = new PsiJavaCommandNode(aClass); 86 | PsiJavaExecutorNode executorNode = new PsiJavaExecutorNode(commandNode, psiMethod); 87 | 88 | return new Pair<>(executorNode, identifier); 89 | 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/marker/ui/ExecutorBadgeFactory.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.marker.ui; 2 | 3 | import com.intellij.ide.HelpTooltip; 4 | import dev.rollczi.litecommands.intellijplugin.api.ExecutorNode; 5 | import dev.rollczi.litecommands.intellijplugin.icon.LiteIcons; 6 | import dev.rollczi.litecommands.intellijplugin.ui.LiteActionBadge; 7 | import dev.rollczi.litecommands.intellijplugin.ui.LiteBox; 8 | import dev.rollczi.litecommands.intellijplugin.ui.LiteColors; 9 | import dev.rollczi.litecommands.intellijplugin.ui.LiteComponent; 10 | import dev.rollczi.litecommands.intellijplugin.ui.LiteMargin; 11 | import javax.swing.JComponent; 12 | 13 | public final class ExecutorBadgeFactory { 14 | 15 | private ExecutorBadgeFactory() { 16 | } 17 | 18 | public static LiteComponent create(ExecutorNode executor, JComponent component) { 19 | String structure = executor.structure(); 20 | 21 | LiteActionBadge badge = new LiteActionBadge( 22 | structure, 23 | LiteColors.GRAY, 24 | LiteColors.GRAY_LIGHT, 25 | LiteIcons.EXECUTOR_ELEMENT, 26 | LiteMargin.SMALL 27 | ); 28 | 29 | badge.addListener((event) -> executor.navigatable().highlight()); 30 | 31 | badge.addHoverListener(mouseEvent -> { 32 | HelpTooltip tooltip = new HelpTooltip(); 33 | 34 | tooltip.setTitle("Executor"); 35 | tooltip.setLink(structure, () -> executor.navigatable().highlight()); 36 | tooltip.setDescription(structure); 37 | tooltip.installOn(component); 38 | }); 39 | 40 | return LiteBox.invisible(badge).margined(LiteMargin.TINY); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/navigatable/NavigatableReference.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.navigatable; 2 | 3 | import com.intellij.platform.backend.navigation.NavigationRequest; 4 | import com.intellij.pom.Navigatable; 5 | import com.intellij.psi.PsiElement; 6 | import dev.rollczi.litecommands.intellijplugin.util.HighlightUtil; 7 | import java.util.Optional; 8 | import java.util.function.Supplier; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public class NavigatableReference implements Navigatable { 12 | 13 | private final Supplier> source; 14 | private final Supplier> psiElementSource; 15 | 16 | 17 | NavigatableReference(Supplier source) { 18 | this(source, () -> null); 19 | } 20 | 21 | NavigatableReference(Supplier source, Supplier psiElementSource) { 22 | this.source = () -> Optional.ofNullable(source.get()); 23 | this.psiElementSource = () -> Optional.ofNullable(psiElementSource.get()); 24 | } 25 | 26 | @Override 27 | public @Nullable NavigationRequest navigationRequest() { 28 | return source.get() 29 | .map(Navigatable::navigationRequest) 30 | .orElse(null); 31 | 32 | } 33 | 34 | @Override 35 | public void navigate(boolean requestFocus) { 36 | source.get() 37 | .ifPresent(navigatable -> navigatable.navigate(requestFocus)); 38 | } 39 | 40 | @Override 41 | public boolean canNavigate() { 42 | return source.get() 43 | .map(Navigatable::canNavigate) 44 | .orElse(false); 45 | } 46 | 47 | @Override 48 | public boolean canNavigateToSource() { 49 | return source.get() 50 | .map(Navigatable::canNavigateToSource) 51 | .orElse(false); 52 | } 53 | 54 | public Optional getPsiElement() { 55 | return psiElementSource.get(); 56 | } 57 | 58 | public static NavigatableReference of(Supplier source) { 59 | return new NavigatableReference(source, () -> { 60 | Navigatable navigatable = source.get(); 61 | 62 | if (navigatable instanceof PsiElement) { 63 | return (PsiElement) navigatable; 64 | } 65 | 66 | return null; 67 | }); 68 | } 69 | 70 | public static NavigatableReference empty() { 71 | return new NavigatableReference(() -> null); 72 | } 73 | 74 | public static NavigatableReference ofPsiElement(Supplier source) { 75 | return new NavigatableReference(() -> { 76 | PsiElement psiElement = source.get(); 77 | 78 | if (psiElement instanceof Navigatable) { 79 | return (Navigatable) psiElement; 80 | } 81 | 82 | return null; 83 | }, source); 84 | } 85 | 86 | public void highlight() { 87 | psiElementSource.get().ifPresent(psiElement -> { 88 | HighlightUtil.highlight(psiElement); 89 | }); 90 | 91 | source.get().ifPresent(navigatable -> { 92 | navigatable.navigate(true); 93 | }); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/popup/LitePopupFactory.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.popup; 2 | 3 | import com.intellij.openapi.ui.popup.IconButton; 4 | import com.intellij.openapi.ui.popup.JBPopup; 5 | import com.intellij.openapi.ui.popup.JBPopupFactory; 6 | import com.intellij.ui.awt.RelativePoint; 7 | 8 | import javax.swing.*; 9 | import java.awt.*; 10 | import java.awt.event.MouseEvent; 11 | import java.util.Collections; 12 | import java.util.Set; 13 | import java.util.WeakHashMap; 14 | 15 | public final class LitePopupFactory { 16 | 17 | private static final Set popups = Collections.newSetFromMap(new WeakHashMap<>()); 18 | 19 | public static void closePopups() { 20 | for (JBPopup popup : popups) { 21 | popup.cancel(); 22 | } 23 | 24 | popups.clear(); 25 | } 26 | 27 | public static void showPopup(String name, String footer, Icon titleIcon, JComponent component, MouseEvent event) { 28 | JBPopup popup = JBPopupFactory.getInstance() 29 | .createComponentPopupBuilder(component, null) 30 | .setTitle(name) 31 | .setTitleIcon(new IconButton(name, titleIcon, titleIcon, titleIcon)) 32 | .setAdText(footer) 33 | .setMovable(true) 34 | .setResizable(true) 35 | .createPopup(); 36 | 37 | Dimension size = component.getPreferredSize(); 38 | size.width += 40; 39 | popup.setMinimumSize(size); 40 | 41 | popup.setRequestFocus(true); 42 | popup.show(new RelativePoint(event)); 43 | 44 | popups.add(popup); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/quickfix/ChangeParameterTypeQuickFix.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.quickfix; 2 | 3 | import com.intellij.codeInspection.ProblemDescriptor; 4 | import com.intellij.openapi.editor.Document; 5 | import com.intellij.openapi.editor.RangeMarker; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.PsiFile; 8 | import com.intellij.psi.PsiParameter; 9 | import com.intellij.psi.PsiTypeElement; 10 | import dev.rollczi.litecommands.intellijplugin.util.PsiImportUtil; 11 | import java.util.function.Function; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | public class ChangeParameterTypeQuickFix extends ReplaceQuickFix { 15 | 16 | private final String[] imports; 17 | 18 | public ChangeParameterTypeQuickFix(Function info, PsiParameter parameter, Class type) { 19 | this(info, parameter, oldType -> type.getSimpleName(), type.getName()); 20 | } 21 | 22 | public ChangeParameterTypeQuickFix(Function info, PsiParameter parameter, Function mapper, String... imports) { 23 | super( 24 | info.apply(mappedType(parameter, mapper)), 25 | createTypeRange(parameter), 26 | mappedType(parameter, mapper) 27 | ); 28 | 29 | this.imports = imports; 30 | } 31 | 32 | private static String mappedType(PsiParameter parameter, Function mapper) { 33 | return mapper.apply(parameter.getType().getPresentableText()); 34 | } 35 | 36 | private static RangeMarker createTypeRange(PsiParameter parameter) { 37 | PsiFile file = parameter.getContainingFile(); 38 | Document document = file.getViewProvider().getDocument(); 39 | PsiTypeElement typeElement = parameter.getTypeElement(); 40 | 41 | if (typeElement == null) { 42 | return document.createRangeMarker(0, 0); 43 | } 44 | 45 | return document.createRangeMarker(typeElement.getTextRange()); 46 | } 47 | 48 | @Override 49 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { 50 | super.applyFix(project, descriptor); 51 | 52 | for (String importType : imports) { 53 | PsiImportUtil.importClass(descriptor.getPsiElement(), importType); 54 | } 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/quickfix/ReplaceQuickFix.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.quickfix; 2 | 3 | import com.intellij.codeInspection.LocalQuickFix; 4 | import com.intellij.codeInspection.ProblemDescriptor; 5 | import com.intellij.openapi.editor.Document; 6 | import com.intellij.openapi.editor.RangeMarker; 7 | import com.intellij.openapi.project.Project; 8 | import com.intellij.psi.PsiDocumentManager; 9 | import com.intellij.psi.PsiFile; 10 | import java.util.concurrent.atomic.AtomicBoolean; 11 | import java.util.function.Consumer; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | public class ReplaceQuickFix implements LocalQuickFix { 15 | 16 | private final AtomicBoolean applied = new AtomicBoolean(false); 17 | 18 | private final String info; 19 | private final RangeMarker rangeMarker; 20 | private final CharSequence charSequence; 21 | private final Runnable documentConsumer; 22 | 23 | public ReplaceQuickFix(String info, RangeMarker rangeMarker, CharSequence charSequence, Runnable documentConsumer) { 24 | this.info = info; 25 | this.rangeMarker = rangeMarker; 26 | this.charSequence = charSequence; 27 | this.documentConsumer = documentConsumer; 28 | } 29 | 30 | public ReplaceQuickFix(String info, RangeMarker rangeMarker, CharSequence charSequence) { 31 | this(info, rangeMarker, charSequence, () -> {}); 32 | } 33 | 34 | @Override 35 | public String getFamilyName() { 36 | return this.info; 37 | } 38 | 39 | @Override 40 | public ReplaceQuickFix getFileModifierForPreview(@NotNull PsiFile target) { 41 | return new ReplaceQuickFix(info, rangeMarker, charSequence); 42 | } 43 | 44 | @Override 45 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { 46 | if (!applied.compareAndSet(false, true)) return; 47 | 48 | PsiFile file = descriptor.getPsiElement().getContainingFile(); 49 | if (file == null) { 50 | return; 51 | } 52 | 53 | Document doc = file.getViewProvider().getDocument(); 54 | if (doc == null) { 55 | return; 56 | } 57 | 58 | if (rangeMarker.isValid()) { 59 | doc.replaceString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), charSequence); 60 | } 61 | 62 | PsiDocumentManager.getInstance(project).commitDocument(doc); 63 | documentConsumer.run(); 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/quickfix/WrapParameterTypeQuickFix.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.quickfix; 2 | 3 | import com.intellij.codeInspection.ProblemDescriptor; 4 | import com.intellij.openapi.editor.Document; 5 | import com.intellij.openapi.editor.RangeMarker; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.PsiFile; 8 | import com.intellij.psi.PsiParameter; 9 | import com.intellij.psi.PsiTypeElement; 10 | import dev.rollczi.litecommands.intellijplugin.util.PsiImportUtil; 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | public class WrapParameterTypeQuickFix extends ReplaceQuickFix { 14 | 15 | private final String importType; 16 | 17 | public WrapParameterTypeQuickFix(PsiParameter parameter, Class type) { 18 | this(parameter, type.getSimpleName(), type.getName()); 19 | } 20 | 21 | public WrapParameterTypeQuickFix(PsiParameter parameter, String type, String importType) { 22 | super( 23 | "Replace to " + getWrappedType(parameter, type), 24 | createTypeRange(parameter), 25 | getWrappedType(parameter, type) 26 | ); 27 | 28 | this.importType = importType; 29 | } 30 | 31 | private static @NotNull String getWrappedType(PsiParameter parameter, String type) { 32 | return type + "<" + parameter.getType().getPresentableText() + ">"; 33 | } 34 | 35 | private static RangeMarker createTypeRange(PsiParameter parameter) { 36 | PsiFile file = parameter.getContainingFile(); 37 | Document document = file.getViewProvider().getDocument(); 38 | PsiTypeElement typeElement = parameter.getTypeElement(); 39 | 40 | if (typeElement == null) { 41 | return document.createRangeMarker(0, 0); 42 | } 43 | 44 | return document.createRangeMarker(typeElement.getTextRange()); 45 | } 46 | 47 | @Override 48 | public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { 49 | super.applyFix(project, descriptor); 50 | PsiImportUtil.importClass(descriptor.getPsiElement(), importType); 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/settings/LiteCommandsConfigurable.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.settings; 2 | 3 | import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; 4 | import com.intellij.codeInsight.daemon.impl.InlayHintsPassFactoryInternal; 5 | import com.intellij.openapi.options.Configurable; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.openapi.project.ProjectManager; 8 | import com.intellij.openapi.util.NlsContexts; 9 | import javax.swing.JComponent; 10 | import org.jetbrains.annotations.Nullable; 11 | 12 | public class LiteCommandsConfigurable implements Configurable { 13 | 14 | private final LiteCommandsSettings settings; 15 | private final LiteCommandsSettings editedSettings; 16 | 17 | LiteCommandsConfigurable() { 18 | this.settings = LiteCommandsSettings.getInstance(); 19 | this.editedSettings = settings.copy(); 20 | } 21 | 22 | @Override 23 | public @NlsContexts.ConfigurableName String getDisplayName() { 24 | return "LiteCommands Settings"; 25 | } 26 | 27 | @Override 28 | public @Nullable JComponent createComponent() { 29 | return new LiteSettingsBox() 30 | .withCheckBox("Show argument hints", editedSettings.showArgumentHints, value -> editedSettings.showArgumentHints = value); 31 | } 32 | 33 | @Override 34 | public boolean isModified() { 35 | return !editedSettings.equals(settings); 36 | } 37 | 38 | @Override 39 | public void apply() { 40 | settings.loadState(editedSettings); 41 | 42 | // reload inlay hints 43 | InlayHintsPassFactoryInternal.Companion.forceHintsUpdateOnNextPass(); 44 | 45 | for (Project openProject : ProjectManager.getInstance().getOpenProjects()) { 46 | DaemonCodeAnalyzer.getInstance(openProject).restart(); 47 | } 48 | } 49 | 50 | @Override 51 | public void reset() { 52 | editedSettings.loadState(settings.getState()); 53 | } 54 | 55 | public LiteCommandsSettings getEdited() { 56 | return editedSettings; 57 | } 58 | 59 | public static LiteCommandsConfigurable createConfigurable() { 60 | return new LiteCommandsConfigurable(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/settings/LiteCommandsSettings.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.settings; 2 | 3 | import com.intellij.openapi.application.ApplicationManager; 4 | import com.intellij.openapi.components.PersistentStateComponent; 5 | import com.intellij.openapi.components.Service; 6 | import com.intellij.openapi.components.State; 7 | import com.intellij.openapi.components.Storage; 8 | import com.intellij.util.xmlb.XmlSerializerUtil; 9 | import java.util.Objects; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | @Service 13 | @State( 14 | name = "LiteCommandsSettings", 15 | storages = { @Storage("litecommands.xml") } 16 | ) 17 | public final class LiteCommandsSettings implements PersistentStateComponent { 18 | 19 | public boolean showArgumentHints = true; 20 | 21 | @Override 22 | public LiteCommandsSettings getState() { 23 | return this; 24 | } 25 | 26 | @Override 27 | public void loadState(@NotNull LiteCommandsSettings liteCommandsSettings) { 28 | XmlSerializerUtil.copyBean(liteCommandsSettings, this); 29 | } 30 | 31 | public LiteCommandsSettings copy() { 32 | return XmlSerializerUtil.createCopy(this); 33 | } 34 | 35 | public static LiteCommandsSettings getInstance() { 36 | return ApplicationManager.getApplication().getService(LiteCommandsSettings.class); 37 | } 38 | 39 | @Override 40 | public boolean equals(Object o) { 41 | if (this == o) return true; 42 | if (o == null || getClass() != o.getClass()) return false; 43 | LiteCommandsSettings that = (LiteCommandsSettings) o; 44 | return showArgumentHints == that.showArgumentHints; 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return Objects.hash(showArgumentHints); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/settings/LiteSettingsBox.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.settings; 2 | 3 | import com.intellij.ui.components.JBCheckBox; 4 | import dev.rollczi.litecommands.intellijplugin.ui.LiteBox; 5 | import java.util.function.Consumer; 6 | 7 | public class LiteSettingsBox extends LiteBox { 8 | 9 | public LiteSettingsBox withCheckBox(String text, boolean selected, Consumer consumer) { 10 | JBCheckBox checkBox = new JBCheckBox(text); 11 | checkBox.setSelected(selected); 12 | checkBox.addActionListener(e -> consumer.accept(checkBox.isSelected())); 13 | add(checkBox); 14 | 15 | return this; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/suppressor/ClassUnusedInspectSuppressor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.suppressor; 2 | 3 | import com.intellij.codeInspection.InspectionSuppressor; 4 | import com.intellij.codeInspection.SuppressQuickFix; 5 | import com.intellij.psi.PsiClass; 6 | import com.intellij.psi.PsiElement; 7 | import com.intellij.psi.PsiIdentifier; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public class ClassUnusedInspectSuppressor implements InspectionSuppressor { 12 | 13 | @Override 14 | public boolean isSuppressedFor(@NotNull PsiElement element, @NotNull String toolId) { 15 | if (!toolId.equals(SuppressUtils.UNUSED_DECLARATION)) { 16 | return false; 17 | } 18 | 19 | if (!(element instanceof PsiIdentifier)) { 20 | return false; 21 | } 22 | 23 | PsiElement parent = element.getParent(); 24 | 25 | if (!(parent instanceof PsiClass psiClass)) { 26 | return false; 27 | } 28 | 29 | return SuppressUtils.isInjectClass(psiClass); 30 | } 31 | 32 | @Override 33 | public SuppressQuickFix @NotNull [] getSuppressActions(@Nullable PsiElement element, @NotNull String toolId) { 34 | return SuppressQuickFix.EMPTY_ARRAY; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/suppressor/ConstructorUnusedInspectSuppressor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.suppressor; 2 | 3 | import com.intellij.codeInspection.InspectionSuppressor; 4 | import com.intellij.codeInspection.SuppressQuickFix; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.psi.PsiIdentifier; 7 | import com.intellij.psi.PsiMethod; 8 | import org.jetbrains.annotations.NotNull; 9 | import org.jetbrains.annotations.Nullable; 10 | 11 | public class ConstructorUnusedInspectSuppressor implements InspectionSuppressor { 12 | 13 | @Override 14 | public boolean isSuppressedFor(@NotNull PsiElement element, @NotNull String toolId) { 15 | if (!toolId.equals(SuppressUtils.UNUSED_DECLARATION)) { 16 | return false; 17 | } 18 | 19 | if (!(element instanceof PsiIdentifier)) { 20 | return false; 21 | } 22 | 23 | PsiElement parent = element.getParent(); 24 | 25 | if (!(parent instanceof PsiMethod psiMethod)) { 26 | return false; 27 | } 28 | 29 | return SuppressUtils.isInjectConstructor(psiMethod); 30 | } 31 | 32 | @Override 33 | public SuppressQuickFix @NotNull [] getSuppressActions(@Nullable PsiElement element, @NotNull String toolId) { 34 | return SuppressQuickFix.EMPTY_ARRAY; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/suppressor/ExecutorUnusedInspectSuppressor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.suppressor; 2 | 3 | import com.intellij.codeInspection.*; 4 | import com.intellij.psi.*; 5 | import dev.rollczi.litecommands.annotations.execute.Execute; 6 | import org.jetbrains.annotations.NotNull; 7 | import org.jetbrains.annotations.Nullable; 8 | 9 | public class ExecutorUnusedInspectSuppressor implements InspectionSuppressor { 10 | 11 | @Override 12 | public boolean isSuppressedFor(@NotNull PsiElement element, @NotNull String toolId) { 13 | if (!toolId.equals(SuppressUtils.UNUSED_DECLARATION)) { 14 | return false; 15 | } 16 | 17 | if (!(element instanceof PsiIdentifier)) { 18 | return false; 19 | } 20 | 21 | PsiElement parent = element.getParent(); 22 | 23 | if (!(parent instanceof PsiMethod psiMethod)) { 24 | return false; 25 | } 26 | 27 | PsiAnnotation execute = psiMethod.getAnnotation(Execute.class.getName()); 28 | 29 | return execute != null; 30 | } 31 | 32 | @Override 33 | public SuppressQuickFix @NotNull [] getSuppressActions(@Nullable PsiElement element, @NotNull String toolId) { 34 | return SuppressQuickFix.EMPTY_ARRAY; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/suppressor/NullableProblemsPrimitiveSuppressor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.suppressor; 2 | 3 | import com.intellij.codeInspection.InspectionSuppressor; 4 | import com.intellij.codeInspection.SuppressQuickFix; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.psi.PsiMethod; 7 | import com.intellij.psi.PsiModifierList; 8 | import com.intellij.psi.PsiParameter; 9 | import com.intellij.psi.PsiParameterList; 10 | import dev.rollczi.litecommands.intellijplugin.util.LiteTypeChecks; 11 | import dev.rollczi.litecommands.intellijplugin.util.LiteAnnotationChecks; 12 | import org.jetbrains.annotations.NotNull; 13 | import org.jetbrains.annotations.Nullable; 14 | 15 | public class NullableProblemsPrimitiveSuppressor implements InspectionSuppressor { 16 | 17 | @Override 18 | public boolean isSuppressedFor(@NotNull PsiElement element, @NotNull String toolId) { 19 | if (!toolId.equals(SuppressUtils.NULLABLE_PROBLEMS)) { 20 | return false; 21 | } 22 | 23 | if (!(element.getParent() instanceof PsiModifierList modifierList)) { 24 | return false; 25 | } 26 | 27 | if (!(modifierList.getParent() instanceof PsiParameter psiParameter)) { 28 | return false; 29 | } 30 | 31 | if (!LiteTypeChecks.isPrimitiveType(psiParameter.getType())) { 32 | return false; 33 | } 34 | 35 | if (!(psiParameter.getParent() instanceof PsiParameterList parameterList)) { 36 | return false; 37 | } 38 | 39 | if (!(parameterList.getParent() instanceof PsiMethod psiMethod)) { 40 | return false; 41 | } 42 | 43 | return LiteAnnotationChecks.isCommandExecutor(psiMethod); 44 | } 45 | 46 | @Override 47 | public SuppressQuickFix @NotNull [] getSuppressActions(@Nullable PsiElement element, @NotNull String toolId) { 48 | return SuppressQuickFix.EMPTY_ARRAY; 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/suppressor/OptionalArgumentSuppressor.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.suppressor; 2 | 3 | import com.intellij.codeInspection.InspectionSuppressor; 4 | import com.intellij.codeInspection.SuppressQuickFix; 5 | import com.intellij.psi.PsiElement; 6 | import com.intellij.psi.PsiMethod; 7 | import com.intellij.psi.PsiParameter; 8 | import com.intellij.psi.PsiParameterList; 9 | import dev.rollczi.litecommands.intellijplugin.util.LiteAnnotationChecks; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | public class OptionalArgumentSuppressor implements InspectionSuppressor { 14 | 15 | @Override 16 | public boolean isSuppressedFor(@NotNull PsiElement element, @NotNull String toolId) { 17 | if (!toolId.equals(SuppressUtils.OPTIONAL_FIELD_OR_PARAMETER_TYPE)) { 18 | return false; 19 | } 20 | 21 | if (!(element.getParent() instanceof PsiParameter psiParameter)) { 22 | return false; 23 | } 24 | 25 | if (!(psiParameter.getParent() instanceof PsiParameterList parameterList)) { 26 | return false; 27 | } 28 | 29 | if (!(parameterList.getParent() instanceof PsiMethod psiMethod)) { 30 | return false; 31 | } 32 | 33 | return LiteAnnotationChecks.isCommandExecutor(psiMethod); 34 | } 35 | 36 | @Override 37 | public SuppressQuickFix @NotNull [] getSuppressActions(@Nullable PsiElement element, @NotNull String toolId) { 38 | return SuppressQuickFix.EMPTY_ARRAY; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/suppressor/SuppressUtils.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.suppressor; 2 | 3 | import com.intellij.psi.PsiAnnotation; 4 | import com.intellij.psi.PsiClass; 5 | import com.intellij.psi.PsiMethod; 6 | import dev.rollczi.litecommands.intellijplugin.util.LiteAnnotationChecks; 7 | import java.util.Set; 8 | 9 | public class SuppressUtils { 10 | 11 | public final static String UNUSED_DECLARATION = "UnusedDeclaration"; 12 | public final static String OPTIONAL_FIELD_OR_PARAMETER_TYPE = "OptionalUsedAsFieldOrParameterType"; 13 | public final static String NULLABLE_PROBLEMS = "NullableProblems"; 14 | 15 | private final static Set INJECT_ANNOTATIONS = Set.of( 16 | "Inject", 17 | "Autowired" 18 | ); 19 | 20 | public static boolean isInjectClass(PsiClass psiClass) { 21 | if (!LiteAnnotationChecks.isCommand(psiClass)) { 22 | return false; 23 | } 24 | 25 | PsiMethod[] constructors = psiClass.getConstructors(); 26 | 27 | for (PsiMethod constructor : constructors) { 28 | if (isInjectConstructor(constructor)) { 29 | return true; 30 | } 31 | } 32 | 33 | return false; 34 | } 35 | 36 | public static boolean isInjectConstructor(PsiMethod psiMethod) { 37 | if (!psiMethod.isConstructor()) { 38 | return false; 39 | } 40 | 41 | PsiClass containingClass = psiMethod.getContainingClass(); 42 | 43 | if (containingClass == null) { 44 | return false; 45 | } 46 | 47 | if (!LiteAnnotationChecks.isCommand(containingClass)) { 48 | return false; 49 | } 50 | 51 | PsiAnnotation[] annotations = psiMethod.getAnnotations(); 52 | 53 | for (PsiAnnotation annotation : annotations) { 54 | String qualifiedName = annotation.getQualifiedName(); 55 | 56 | if (qualifiedName == null) { 57 | continue; 58 | } 59 | 60 | int index = qualifiedName.lastIndexOf('.'); 61 | 62 | if (index == -1) { 63 | continue; 64 | } 65 | 66 | String name = qualifiedName.substring(index + 1); 67 | 68 | if (INJECT_ANNOTATIONS.contains(name)) { 69 | return true; 70 | } 71 | } 72 | 73 | return false; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/table/LiteTableView.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.table; 2 | 3 | import com.intellij.ui.JBColor; 4 | import com.intellij.ui.table.TableView; 5 | import java.awt.Cursor; 6 | import java.awt.Dimension; 7 | import javax.swing.BorderFactory; 8 | 9 | public class LiteTableView extends TableView { 10 | 11 | public LiteTableView() { 12 | this.setShowGrid(false); 13 | this.setCursor(new Cursor(Cursor.HAND_CURSOR)); 14 | this.setFillsViewportHeight(true); 15 | this.setIntercellSpacing(new Dimension(0, 0)); 16 | this.getTableHeader().setBorder(BorderFactory.createLineBorder(JBColor.background())); 17 | this.getTableHeader().setReorderingAllowed(false); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/table/LiteToolbarDecorator.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.table; 2 | 3 | import com.intellij.openapi.actionSystem.ActionToolbarPosition; 4 | import com.intellij.ui.JBColor; 5 | import com.intellij.ui.ToolbarDecorator; 6 | import java.awt.Dimension; 7 | import javax.swing.BorderFactory; 8 | import javax.swing.JTable; 9 | 10 | public final class LiteToolbarDecorator { 11 | 12 | private LiteToolbarDecorator() { 13 | } 14 | 15 | public static ToolbarDecorator createDecorator(JTable table) { 16 | return ToolbarDecorator.createDecorator(table) 17 | .setPanelBorder(BorderFactory.createLineBorder(JBColor.background())) 18 | .setToolbarBorder(BorderFactory.createLineBorder(JBColor.background())) 19 | .setScrollPaneBorder(BorderFactory.createLineBorder(JBColor.background())) 20 | .setToolbarPosition(ActionToolbarPosition.RIGHT) 21 | 22 | .setMinimumSize(new Dimension(250, 0)); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/ui/LiteActionBadge.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.ui; 2 | 3 | import javax.swing.Icon; 4 | import java.awt.Color; 5 | import java.awt.Cursor; 6 | import java.awt.event.MouseAdapter; 7 | import java.awt.event.MouseEvent; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.function.Consumer; 11 | 12 | public class LiteActionBadge extends LiteBadge { 13 | 14 | private final List> listeners = new ArrayList<>(); 15 | private final List> hoverListeners = new ArrayList<>(); 16 | 17 | public LiteActionBadge(Color badgeColor, Color hover, Icon icon, int margin) { 18 | this("", badgeColor, hover, icon, margin); 19 | } 20 | 21 | public LiteActionBadge(String badgeText, Color badgeColor, Color hover, Icon icon, int margin) { 22 | super(badgeText, badgeColor, icon, margin); 23 | this.asComponent().setCursor(new Cursor(Cursor.HAND_CURSOR)); 24 | this.asComponent().addMouseListener(new MouseAdapter() { 25 | @Override 26 | public void mousePressed(MouseEvent e) { 27 | listeners.forEach(consumer -> consumer.accept(e)); 28 | } 29 | 30 | @Override 31 | public void mouseEntered(MouseEvent e) { 32 | setBadgeColor(hover); 33 | hoverListeners.forEach(consumer -> consumer.accept(e)); 34 | } 35 | 36 | @Override 37 | public void mouseExited(MouseEvent e) { 38 | setBadgeColor(badgeColor); 39 | } 40 | }); 41 | } 42 | 43 | public void addListener(Consumer runnable) { 44 | listeners.add(runnable); 45 | } 46 | 47 | public void addHoverListener(Consumer consumer) { 48 | hoverListeners.add(consumer); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/ui/LiteArc.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.ui; 2 | 3 | public class LiteArc { 4 | 5 | public static final int NONE = 0; 6 | public static final int SMALL = 10; 7 | public static final int MEDIUM = 20; 8 | public static final int LARGE = 30; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/ui/LiteBox.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.ui; 2 | 3 | import org.intellij.lang.annotations.MagicConstant; 4 | 5 | import java.awt.*; 6 | import javax.swing.*; 7 | 8 | public class LiteBox extends Box implements LiteComponent { 9 | 10 | private final int arcWidth; 11 | private final int arcHeight; 12 | private final Color color; 13 | 14 | public LiteBox() { 15 | this(LiteColors.NONE, LiteArc.SMALL, LiteArc.SMALL); 16 | } 17 | 18 | public LiteBox(Color color) { 19 | this(color, LiteArc.SMALL, LiteArc.SMALL); 20 | } 21 | 22 | public LiteBox(Color color, @MagicConstant(valuesFromClass = LiteArc.class) int arc) { 23 | this(color, arc, arc); 24 | } 25 | 26 | public LiteBox(Color color, @MagicConstant(valuesFromClass = LiteArc.class) int arcHeight, @MagicConstant(valuesFromClass = LiteArc.class) int arcWidth) { 27 | super(BoxLayout.Y_AXIS); 28 | this.arcWidth = arcWidth; 29 | this.arcHeight = arcHeight; 30 | this.color = color; 31 | 32 | this.setOpaque(false); 33 | this.setBackground(LiteColors.NONE); 34 | this.setAlignmentX(Component.LEFT_ALIGNMENT); 35 | } 36 | 37 | @Override 38 | protected void paintComponent(Graphics g) { 39 | super.paintComponent(g); 40 | Graphics2D g2 = (Graphics2D) g; 41 | 42 | g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 43 | g2.setColor(color); 44 | g2.fillRoundRect(0, 0, getWidth(), getHeight(), arcWidth, arcHeight); 45 | } 46 | 47 | @Override 48 | protected void paintBorder(Graphics g) { 49 | // To avoid painting the default border of the container 50 | } 51 | 52 | public LiteMargin margined(@MagicConstant(valuesFromClass = LiteMargin.class) int margin) { 53 | return LiteMargin.of(margin, this); 54 | } 55 | 56 | public static LiteBox of(Component... components) { 57 | LiteBox box = new LiteBox(); 58 | 59 | for (Component component : components) { 60 | box.add(component); 61 | } 62 | 63 | return box; 64 | } 65 | 66 | public static LiteBox invisible(Component... components) { 67 | LiteBox box = new LiteBox(LiteColors.NONE); 68 | 69 | for (Component component : components) { 70 | box.add(component); 71 | } 72 | 73 | return box; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/ui/LiteColors.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.ui; 2 | 3 | import com.intellij.ui.JBColor; 4 | import java.awt.*; 5 | 6 | public final class LiteColors { 7 | 8 | private LiteColors() { 9 | } 10 | 11 | 12 | public static final Color NONE = new JBColor(new Color(0, 0, 0, 0), new Color(0, 0, 0, 0)); 13 | public static final Color GRAY_DARK = new JBColor(new Color(0, 0, 0, 35), new Color(0, 0, 0, 35)); 14 | public static final Color GRAY = new JBColor(new Color(0, 0, 0, 25), new Color(0, 0, 0, 25)); 15 | public static final Color GRAY_LIGHT = new JBColor(new Color(0, 0, 0, 15), new Color(0, 0, 0, 15)); 16 | public static final Color RED = new JBColor(new Color(140, 0, 0, 20), new Color(140, 0, 0, 20)); 17 | public static final Color HIGH_LIGHT = new JBColor(new Color(50, 180, 50, 50), new Color(50, 180, 50, 50)); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/ui/LiteComponent.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.ui; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | 6 | public interface LiteComponent { 7 | 8 | default LiteComponent with(LiteComponent liteComponent) { 9 | return this.withComponent((Component) liteComponent); 10 | } 11 | 12 | default LiteComponent withComponent(Component liteComponent) { 13 | if (!(this instanceof Container)) { 14 | return this; 15 | } 16 | 17 | this.asComponent().add(liteComponent); 18 | return this; 19 | } 20 | 21 | default JComponent asComponent() { 22 | if (!(this instanceof JComponent)) { 23 | throw new UnsupportedOperationException(); 24 | } 25 | 26 | return (JComponent) this; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/ui/LiteMargin.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.ui; 2 | 3 | import org.intellij.lang.annotations.MagicConstant; 4 | 5 | import java.awt.*; 6 | import javax.swing.*; 7 | 8 | public class LiteMargin extends Box implements LiteComponent { 9 | 10 | public static final int NONE = 0; 11 | public static final int TINY = 3; 12 | public static final int SMALLER = 5; 13 | public static final int SMALL = 10; 14 | public static final int NORMAL = 15; 15 | public static final int MEDIUM = 20; 16 | public static final int BIG = 25; 17 | public static final int LARGE = 30; 18 | 19 | public LiteMargin(int margin) { 20 | this(margin, margin, margin, margin); 21 | } 22 | 23 | public LiteMargin(int topBottomMargin, int leftRightMargin) { 24 | this(topBottomMargin, leftRightMargin, topBottomMargin, leftRightMargin); 25 | } 26 | 27 | public LiteMargin(int topMargin, int leftMargin, int bottomMargin, int rightMargin) { 28 | super(BoxLayout.Y_AXIS); 29 | this.setAlignmentX(Component.LEFT_ALIGNMENT); 30 | 31 | this.setOpaque(false); 32 | this.setBorder(BorderFactory.createEmptyBorder(topMargin, leftMargin, bottomMargin, rightMargin)); 33 | } 34 | 35 | public static LiteMargin of(@MagicConstant(valuesFromClass = LiteMargin.class) int margin, LiteComponent... components) { 36 | LiteMargin liteMargin = new LiteMargin(margin, margin, margin, margin); 37 | for (LiteComponent component : components) { 38 | liteMargin.with(component); 39 | } 40 | return liteMargin; 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/ui/LiteTitledSeparator.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.ui; 2 | 3 | import com.intellij.openapi.util.NlsContexts; 4 | import com.intellij.ui.TitledSeparator; 5 | import com.intellij.util.ui.JBFont; 6 | 7 | import javax.swing.*; 8 | 9 | public class LiteTitledSeparator extends TitledSeparator { 10 | 11 | public LiteTitledSeparator(Icon icon, @NlsContexts.Separator String text) { 12 | super(text); 13 | getLabel().setIcon(icon); 14 | getLabel().setIconTextGap(10); 15 | setTitleFont(JBFont.regular().asBold()); 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/usage/Usage.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.usage; 2 | 3 | import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector; 4 | import com.intellij.psi.PsiElement; 5 | import com.intellij.usageView.UsageInfo; 6 | import com.intellij.usages.ReadWriteAccessUsageInfo2UsageAdapter; 7 | 8 | public class Usage extends ReadWriteAccessUsageInfo2UsageAdapter { 9 | 10 | public Usage(UsageInfo usageInfo, ReadWriteAccessDetector.Access rwAccess) { 11 | super(usageInfo, rwAccess); 12 | } 13 | 14 | public Usage(PsiElement usageInfo, ReadWriteAccessDetector.Access rwAccess) { 15 | super(new UsageInfo(usageInfo), rwAccess); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/usage/UsageFindUsagesDialog.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.usage; 2 | 3 | import com.intellij.find.findUsages.AbstractFindUsagesDialog; 4 | import com.intellij.find.findUsages.FindUsagesOptions; 5 | import com.intellij.lang.findUsages.DescriptiveNameUtil; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.openapi.util.text.StringUtil; 8 | import com.intellij.psi.PsiElement; 9 | import com.intellij.ui.SimpleColoredComponent; 10 | import com.intellij.ui.SimpleTextAttributes; 11 | import com.intellij.usageView.UsageViewUtil; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | class UsageFindUsagesDialog extends AbstractFindUsagesDialog { 15 | 16 | private final PsiElement myPsiElement; 17 | 18 | protected UsageFindUsagesDialog(@NotNull Project project, @NotNull FindUsagesOptions findUsagesOptions, PsiElement myPsiElement) { 19 | super(project, findUsagesOptions, false, false, false, true, true); 20 | this.myPsiElement = myPsiElement; 21 | } 22 | 23 | @Override 24 | public void configureLabelComponent(@NotNull SimpleColoredComponent coloredComponent) { 25 | coloredComponent.append(StringUtil.capitalize(UsageViewUtil.getType(this.myPsiElement))); 26 | coloredComponent.append(" "); 27 | coloredComponent.append(DescriptiveNameUtil.getDescriptiveName(this.myPsiElement), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/usage/UsageProvider.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.usage; 2 | 3 | import java.util.Collection; 4 | 5 | public interface UsageProvider { 6 | 7 | Collection getUsages(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/usage/UsageService.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.usage; 2 | 3 | import com.intellij.find.actions.ShowUsagesManager; 4 | import com.intellij.find.actions.ShowUsagesParameters; 5 | import com.intellij.openapi.application.ApplicationManager; 6 | import com.intellij.openapi.components.Service; 7 | import com.intellij.openapi.editor.Editor; 8 | import com.intellij.openapi.project.Project; 9 | import com.intellij.openapi.util.IntRef; 10 | import com.intellij.psi.PsiElement; 11 | import com.intellij.ui.awt.RelativePoint; 12 | import com.intellij.usages.impl.UsageViewPopupManager; 13 | import java.awt.Point; 14 | 15 | @Service 16 | public final class UsageService { 17 | 18 | public void show(String title, String optionsString, Editor editor, PsiElement element, Point point, UsageProvider usageProvider) { 19 | Project project = element.getProject(); 20 | ShowUsagesManager manager = ShowUsagesManager.getInstance(project); 21 | UsageViewPopupManager service = project.getService(UsageViewPopupManager.class); 22 | 23 | manager.showElementUsagesWithResult( 24 | new ShowUsagesParameters( 25 | project, 26 | editor, 27 | new RelativePoint(point), 28 | new IntRef(100), 29 | 100 30 | ), 31 | new UsageActionHandler(title, optionsString, element, usageProvider), 32 | service.createUsageViewPopup(element.getLanguage()) 33 | ); 34 | 35 | } 36 | 37 | public static UsageService getInstance() { 38 | return ApplicationManager.getApplication().getService(UsageService.class); 39 | } 40 | 41 | } 42 | 43 | /* 44 | class UsageViewPopup extends UsageViewImpl { 45 | public UsageViewPopup(Project project) { 46 | super(project, getUsageViewPresentation(), UsageTarget.EMPTY_ARRAY, null); 47 | } 48 | 49 | private static UsageViewPresentation getUsageViewPresentation() { 50 | UsageViewPresentation var2 = new UsageViewPresentation(); 51 | var2.setDetachedMode(true); 52 | return var2; 53 | } 54 | 55 | @Override 56 | public @NotNull UsageViewSettings getUsageViewSettings() { 57 | return ShowUsagesSettings.Companion.getInstance().getState(); 58 | } 59 | }*/ 60 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/HighlightUtil.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.openapi.editor.Editor; 4 | import com.intellij.openapi.editor.markup.HighlighterTargetArea; 5 | import com.intellij.openapi.editor.markup.MarkupModel; 6 | import com.intellij.openapi.editor.markup.RangeHighlighter; 7 | import com.intellij.openapi.editor.markup.TextAttributes; 8 | import com.intellij.openapi.fileEditor.FileEditor; 9 | import com.intellij.openapi.fileEditor.FileEditorManager; 10 | import com.intellij.openapi.fileEditor.TextEditor; 11 | import com.intellij.openapi.util.TextRange; 12 | import com.intellij.psi.PsiElement; 13 | import com.intellij.util.concurrency.AppExecutorUtil; 14 | import dev.rollczi.litecommands.intellijplugin.ui.LiteColors; 15 | import java.awt.Font; 16 | import java.util.concurrent.ScheduledExecutorService; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | public final class HighlightUtil { 20 | 21 | 22 | public static final int HIGHLIGHT_REMOVAL_DELAY = 1000; 23 | 24 | private HighlightUtil() { 25 | } 26 | 27 | public static void highlight(PsiElement psiElement) { 28 | FileEditorManager manager = FileEditorManager.getInstance(psiElement.getProject()); 29 | FileEditor[] fileEditors = manager.openFile(psiElement.getContainingFile().getVirtualFile(), true); 30 | 31 | for (FileEditor fileEditor : fileEditors) { 32 | if (fileEditor instanceof TextEditor textEditor) { 33 | Editor editor = textEditor.getEditor(); 34 | MarkupModel markupModel = editor.getMarkupModel(); 35 | TextRange range = psiElement.getTextRange(); 36 | 37 | RangeHighlighter rangeHighlighter = markupModel.addRangeHighlighter( 38 | range.getStartOffset(), 39 | range.getEndOffset(), 40 | Integer.MAX_VALUE, 41 | new TextAttributes(null, LiteColors.HIGH_LIGHT, null, null, Font.PLAIN), 42 | HighlighterTargetArea.EXACT_RANGE 43 | ); 44 | 45 | ScheduledExecutorService executorService = AppExecutorUtil.getAppScheduledExecutorService(); 46 | executorService.schedule(() -> markupModel.removeHighlighter(rangeHighlighter), HIGHLIGHT_REMOVAL_DELAY, TimeUnit.MILLISECONDS); 47 | } 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/IdeaEmptyTask.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.function.Supplier; 6 | 7 | public interface IdeaEmptyTask { 8 | 9 | IdeaEmptyTask then(IdeaTaskType type, Runnable runnable); 10 | 11 | IdeaEmptyTask then(Runnable runnable); 12 | 13 | IdeaTask map(IdeaTaskType type, Supplier function); 14 | 15 | IdeaTask flatMap(IdeaTaskType type, Supplier> function); 16 | 17 | IdeaTask flatMap(Supplier> function); 18 | 19 | IdeaTask ui(Supplier supplier); 20 | 21 | IdeaTask read(Supplier supplier); 22 | 23 | IdeaTask write(Supplier supplier); 24 | 25 | IdeaTask async(Supplier supplier); 26 | 27 | IdeaTask waitForSmart(Project project, Supplier supplier); 28 | 29 | IdeaEmptyTask waitForSmart(Project project, Runnable supplier); 30 | 31 | IdeaEmptyTask waitForSmart(Project project); 32 | 33 | CompletableFuture asFuture(); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/IdeaTaskType.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.openapi.application.ApplicationManager; 4 | import com.intellij.openapi.command.CommandProcessor; 5 | import com.intellij.openapi.command.WriteCommandAction; 6 | import com.intellij.openapi.project.DumbService; 7 | import com.intellij.openapi.project.Project; 8 | import java.util.concurrent.Executor; 9 | 10 | public class IdeaTaskType { 11 | 12 | public static final IdeaTaskType UI = new IdeaTaskType(command -> ApplicationManager.getApplication().invokeLater(command)); 13 | public static final IdeaTaskType READ = new IdeaTaskType(command -> ApplicationManager.getApplication().runReadAction(command)); 14 | public static final IdeaTaskType WRITE = new IdeaTaskType(command -> ApplicationManager.getApplication().runWriteAction(command)); 15 | public static final IdeaTaskType WRITE_INTENT = new IdeaTaskType(command -> ApplicationManager.getApplication().runWriteIntentReadAction(() -> { 16 | ApplicationManager.getApplication().runWriteAction(command); 17 | return null; 18 | })); 19 | 20 | public static final IdeaTaskType ASYNC = new IdeaTaskType(command -> ApplicationManager.getApplication().executeOnPooledThread(command)); 21 | 22 | public static IdeaTaskType smartMode(Project project) { 23 | return new IdeaTaskType(command -> DumbService.getInstance(project).runWhenSmart(command)); 24 | } 25 | 26 | public static IdeaTaskType writeCommand(Project project) { 27 | return new IdeaTaskType(command -> WriteCommandAction.runWriteCommandAction(project, command)); 28 | } 29 | 30 | public static IdeaTaskType command(Project project) { 31 | return new IdeaTaskType(command -> CommandProcessor.getInstance().executeCommand(project, command, null, null)); 32 | } 33 | 34 | private final Executor executor; 35 | 36 | Executor getExecutor() { 37 | return executor; 38 | } 39 | 40 | public IdeaTaskType(Executor executor) { 41 | this.executor = executor; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/LiteAnnotationChecks.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.psi.PsiClass; 4 | import com.intellij.psi.PsiMethod; 5 | import dev.rollczi.litecommands.annotations.command.Command; 6 | import dev.rollczi.litecommands.annotations.command.RootCommand; 7 | import dev.rollczi.litecommands.annotations.execute.Execute; 8 | 9 | public final class LiteAnnotationChecks { 10 | 11 | public static boolean isCommand(PsiClass psiClass) { 12 | return psiClass.getAnnotation(Command.class.getName()) != null || psiClass.getAnnotation(RootCommand.class.getName()) != null; 13 | } 14 | 15 | public static boolean isCommandExecutor(PsiMethod psiMethod) { 16 | return psiMethod.getAnnotation(Execute.class.getName()) != null; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/LiteTypeChecks.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.lang.jvm.types.JvmPrimitiveTypeKind; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.PsiAnnotation; 6 | import com.intellij.psi.PsiType; 7 | import com.intellij.psi.search.GlobalSearchScope; 8 | import dev.rollczi.litecommands.annotations.argument.Arg; 9 | import dev.rollczi.litecommands.annotations.flag.Flag; 10 | import dev.rollczi.litecommands.annotations.join.Join; 11 | import dev.rollczi.litecommands.annotations.optional.OptionalArg; 12 | import java.util.Collection; 13 | import java.util.OptionalDouble; 14 | import java.util.OptionalInt; 15 | import java.util.OptionalLong; 16 | import java.util.Set; 17 | 18 | public class LiteTypeChecks { 19 | 20 | private static final Set OPTIONAL_WRAPPERS = Set.of( 21 | java.util.Optional.class.getName(), 22 | OptionalInt.class.getName(), 23 | OptionalDouble.class.getName(), 24 | OptionalLong.class.getName(), 25 | "panda.std.Option" // legacy support 26 | ); 27 | 28 | private static final Set ARGUMENT_ANNOTATIONS = Set.of( 29 | Arg.class.getName(), 30 | OptionalArg.class.getName(), 31 | Flag.class.getName(), 32 | Join.class.getName() 33 | ); 34 | 35 | public static boolean isOptionalWrapper(PsiType type) { 36 | String canonicalText = type.getCanonicalText(); 37 | return OPTIONAL_WRAPPERS.stream() 38 | .anyMatch(prefix -> canonicalText.startsWith(prefix)); 39 | } 40 | 41 | public static boolean isArgumentAnnotation(PsiAnnotation type) { 42 | String canonicalText = type.getQualifiedName(); 43 | 44 | if (canonicalText == null) { 45 | return false; 46 | } 47 | 48 | return ARGUMENT_ANNOTATIONS.contains(canonicalText); 49 | } 50 | 51 | public static boolean isArrayWrapper(PsiType type, Project project) { 52 | PsiType collectionType = PsiType.getTypeByName(Collection.class.getName(), project, GlobalSearchScope.allScope(project)); 53 | 54 | if (collectionType.isAssignableFrom(type)) { 55 | return true; 56 | } 57 | 58 | if (type.getArrayDimensions() > 0) { 59 | return true; 60 | } 61 | 62 | return false; 63 | } 64 | 65 | public static boolean isPrimitiveType(PsiType type) { 66 | JvmPrimitiveTypeKind primitiveKind = JvmPrimitiveTypeKind.getKindByName(type.getCanonicalText()); 67 | 68 | return primitiveKind != null; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/PsiImportUtil.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.psi.*; 5 | import com.intellij.psi.search.GlobalSearchScope; 6 | 7 | public final class PsiImportUtil { 8 | 9 | private PsiImportUtil() { 10 | } 11 | 12 | public static void importClass(PsiElement source, String classImport) { 13 | importClass(source.getContainingFile(), classImport); 14 | } 15 | 16 | public static void importClass(PsiFile file, String classImport) { 17 | Project project = file.getProject(); 18 | 19 | if (!(file instanceof PsiJavaFile javaFile)) { 20 | throw new RuntimeException("Cannot add import to non-java file"); 21 | } 22 | 23 | JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); 24 | PsiClass annotationClass = javaPsiFacade.findClass(classImport, GlobalSearchScope.allScope(project)); 25 | 26 | if (annotationClass == null) { 27 | throw new RuntimeException("Cannot find annotation class " + classImport); 28 | } 29 | 30 | if (javaFile.findImportReferenceTo(annotationClass) == null) { 31 | javaFile.importClass(annotationClass); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/PsiPrimitiveUtil.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.lang.jvm.types.JvmPrimitiveTypeKind; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.PsiClassType; 6 | import com.intellij.psi.PsiType; 7 | import com.intellij.psi.search.GlobalSearchScope; 8 | 9 | public final class PsiPrimitiveUtil { 10 | 11 | private PsiPrimitiveUtil() { 12 | } 13 | 14 | public static PsiClassType boxPrimitiveType(PsiType type, Project project) { 15 | if (type instanceof PsiClassType) { 16 | return (PsiClassType) type; 17 | } 18 | 19 | JvmPrimitiveTypeKind primitiveKind = JvmPrimitiveTypeKind.getKindByName(type.getCanonicalText()); 20 | 21 | if (primitiveKind == null) { 22 | throw new IllegalArgumentException("Type is not primitive and cannot be boxed"); 23 | } 24 | 25 | return PsiType.getTypeByName(primitiveKind.getBoxedFqn(), project, GlobalSearchScope.allScope(project)); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/dev/rollczi/litecommands/intellijplugin/util/PsiValue.java: -------------------------------------------------------------------------------- 1 | package dev.rollczi.litecommands.intellijplugin.util; 2 | 3 | import com.intellij.psi.PsiElement; 4 | 5 | public record PsiValue(PsiElement source, T value) { 6 | 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/pluginIcon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/application.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/applicationRemote.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/applicationRemote_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/application_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/columnGoldKey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/columnGoldKeyDotIndex.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/columnGoldKeyDotIndex_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/columnGoldKey_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/frame.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/frame_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/goldKey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/goldKey_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/groupByModule.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/groupByModule_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/inlayRenameInComments.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/inlayRenameInCommentsActive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/inlayRenameInCommentsActive_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/inlayRenameInComments_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/mongoFieldGoldKey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/mongoFieldGoldKey_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/ocdRunConfiguration.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/ocdRunConfiguration_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/runParatest.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/runParatest_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/showCurrentFrame.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/expUi/showCurrentFrame_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/litecommandsIcon_class.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 33 | 35 | 38 | 47 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/litecommandsIcon_class_dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 33 | 35 | 38 | 47 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/litecommandsIcon_class_root.svg: -------------------------------------------------------------------------------- 1 | 2 | 14 | 33 | 35 | 38 | 43 | 48 | 55 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/main/resources/assets/icons/litecommandsLogo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/fileTemplates/internal/LiteCommands Command Java.java.ft: -------------------------------------------------------------------------------- 1 | #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end 2 | #parse("File Header.java") 3 | import dev.rollczi.litecommands.annotations.command.Command; 4 | import dev.rollczi.litecommands.annotations.execute.Execute; 5 | 6 | #if ($NAME.toLowerCase().endsWith("command") && $NAME.length() > 7) 7 | #set($realName = $NAME.substring(0, $NAME.length() - 7)) 8 | #else 9 | #set($realName = $NAME) 10 | #end 11 | #if (!$NAME.isEmpty()) 12 | #set($first_letter = $realName.substring(0, 1).toUpperCase()) 13 | #set($the_rest = $realName.substring(1)) 14 | #set($realName = $first_letter + $the_rest) 15 | #end 16 | @Command(name = "${realName.toLowerCase()}") 17 | public class ${realName}Command { 18 | 19 | @Execute 20 | void execute${realName}() { 21 | // Execute the /${realName.toLowerCase()} 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/fileTemplates/internal/LiteCommands Command Kotlin.kt.ft: -------------------------------------------------------------------------------- 1 | #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end 2 | 3 | #parse("File Header.java") 4 | import dev.rollczi.litecommands.annotations.command.Command 5 | import dev.rollczi.litecommands.annotations.execute.Execute 6 | 7 | #if ($NAME.toLowerCase().endsWith("command") && $NAME.length() > 7) 8 | #set($realName = $NAME.substring(0, $NAME.length() - 7)) 9 | #else 10 | #set($realName = $NAME) 11 | #end 12 | #if (!$NAME.isEmpty()) 13 | #set($first_letter = $realName.substring(0, 1).toUpperCase()) 14 | #set($the_rest = $realName.substring(1)) 15 | #set($realName = $first_letter + $the_rest) 16 | #end 17 | @Command(name = "${realName.toLowerCase()}") 18 | class ${realName}Command { 19 | 20 | @Execute 21 | fun execute${realName}() { 22 | // Execute the /${realName.toLowerCase()} 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/fileTemplates/internal/LiteCommands Root Command Java.java.ft: -------------------------------------------------------------------------------- 1 | #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end 2 | #parse("File Header.java") 3 | import dev.rollczi.litecommands.annotations.command.RootCommand; 4 | import dev.rollczi.litecommands.annotations.execute.Execute; 5 | 6 | #if ($NAME.toLowerCase().endsWith("command") && $NAME.length() > 7) 7 | #set($realName = $NAME.substring(0, $NAME.length() - 7)) 8 | #else 9 | #set($realName = $NAME) 10 | #end 11 | #if (!$NAME.isEmpty()) 12 | #set($first_letter = $realName.substring(0, 1).toUpperCase()) 13 | #set($the_rest = $realName.substring(1)) 14 | #set($realName = $first_letter + $the_rest) 15 | #end 16 | @RootCommand 17 | public class ${realName}Command { 18 | 19 | @Execute(name = "${realName.toLowerCase()}") 20 | void execute${realName}() { 21 | // Execute the /${realName.toLowerCase()} 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/resources/fileTemplates/internal/LiteCommands Root Command Kotlin.kt.ft: -------------------------------------------------------------------------------- 1 | #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end 2 | 3 | #parse("File Header.java") 4 | import dev.rollczi.litecommands.annotations.command.RootCommand 5 | import dev.rollczi.litecommands.annotations.execute.Execute 6 | 7 | #if ($NAME.toLowerCase().endsWith("command") && $NAME.length() > 7) 8 | #set($realName = $NAME.substring(0, $NAME.length() - 7)) 9 | #else 10 | #set($realName = $NAME) 11 | #end 12 | #if (!$NAME.isEmpty()) 13 | #set($first_letter = $realName.substring(0, 1).toUpperCase()) 14 | #set($the_rest = $realName.substring(1)) 15 | #set($realName = $first_letter + $the_rest) 16 | #end 17 | @RootCommand 18 | class ${realName}Command { 19 | 20 | @Execute(name = "${realName.toLowerCase()}") 21 | fun execute${realName}() { 22 | // Execute the /${realName.toLowerCase()} 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/ExecuteValidation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Invalid usage of @Execute annotation. 4 |

5 | Reports when attributes route or aliases are invalid. 6 | For example, when route or aliases are defined, but string is empty. 7 |

8 |

9 | Examples of valid values: 10 |

11 | 12 |
    13 |
  • @Execute(route = "add")
  • 14 |
  • @Execute(route = "add user")
  • 15 |
  • @Execute(route = "add user", aliases = "add u")
  • 16 |
  • @Execute(route = "add user", aliases = { "add u", "sub -u" })
  • 17 |
  • @Execute(route = "add user parent")
  • 18 |
19 | 20 |

21 | Examples of invalid values: 22 |

23 |
    24 |
  • @Execute(route = "")
  • 25 |
  • @Execute(route = "add", aliases = "")
  • 26 |
  • @Execute(route = "add ")
  • 27 |
  • @Execute(route = " add")
  • 28 |
  • @Execute(route = " add ")
  • 29 |
  • @Execute(route = "add", aliases = " ")
  • 30 |
  • @Execute(route = " ", aliases = "add")
  • 31 |
  • @Execute(route = "add user")
  • 32 |
33 | 34 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/ExecutorNotAnnotatedParameter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Missing annotation for parameter of executor method. 4 |

5 | Reports when parameter of executor method is not annotated with e.g. 6 | @Arg, 7 | @Join, 8 | @Flag, 9 | @Context or 10 | @Bind 11 |

12 | 13 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/LegacyArg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Migration from legacy 2.x to 3.x version 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/LegacyExecute.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Migration from legacy 2.x to 3.x version 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/LegacyJoin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Migration from legacy 2.x to 3.x version 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/LegacyPermission.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Migration from legacy 2.x to 3.x version 4 | 5 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/LegacyRoute.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Used annotation @Route is deprecated and should be replaced with @Command 4 |

5 | Reports all usages of @Route annotation in the project. 6 |

7 |
8 |

9 | Replace: 10 |

11 |

12 | @Route(name = "name", aliases = { "other", "more" }) 13 |

14 |

15 | to: 16 |

17 |

18 | @Command(name = "name", aliases = { "other", "more" }) 19 |

20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/LegacySection.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Used annotation @Section is deprecated and should be replaced with @Route 4 |

5 | Reports all usages of @Section annotation in the project. 6 |

7 |
8 |

9 | Replace: 10 |

11 |

12 | @Section(route = "name", aliases = { "other", "more" }) 13 |

14 |

15 | to: 16 |

17 |

18 | @Route(name = "name", aliases = { "other", "more" }) 19 |

20 | 21 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/LiteralAnnotation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | @Literal annotation should be used only on String. 4 |

5 | Reports when @Literal annotation is used on a type other than String. 6 |

7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/ParameterMixedAnnotations.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mixed annotations. 4 |

5 | Reports when method parameter has mixed requirement annotations. 6 |

7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/ParameterNullableOptionalPrimitive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Optional argument should not be primitive type. 4 |

5 | Reports when optional argument is primitive type. 6 |

7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/ParameterNullableOptionalWrapped.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Nullable argument should not be Optional. 4 |

5 | Reports when nullable argument is Optional. 6 |

7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/ParameterOptionalIsPrimitive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Optional argument should not be primitive type. 4 |

5 | Reports when optional argument is primitive type. 6 |

7 | 8 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/RouteValidation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Invalid usage of @Route annotation. 4 |

5 | Reports when attributes name or aliases are invalid. 6 | For example, when name or aliases are defined, but string is empty. 7 |

8 | 9 |

10 | Examples of valid values: 11 |

12 | 13 |
    14 |
  • @Route(name = "add")
  • 15 |
  • @Route(name = "add user")
  • 16 |
  • @Route(name = "add user", aliases = "add u")
  • 17 |
  • @Route(name = "add user", aliases = { "add u", "sub -u" })
  • 18 |
  • @Route(name = "add user parent")
  • 19 |
20 | 21 |

22 | Examples of invalid values: 23 |

24 | 25 |
    26 |
  • @Route(name = "")
  • 27 |
  • @Route(name = "add", aliases = "")
  • 28 |
  • @Route(name = "add ")
  • 29 |
  • @Route(name = " add")
  • 30 |
  • @Route(name = " add ")
  • 31 |
  • @Route(name = "add", aliases = " ")
  • 32 |
  • @Route(name = " ", aliases = "add")
  • 33 |
  • @Route(name = "add user")
  • 34 |
35 | 36 | -------------------------------------------------------------------------------- /src/main/resources/inspectionDescriptions/VarargsAnnotation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | @Varargs support only collection types. 4 |

5 | Reports when varargs parameter is not a collection type. 6 |

7 |

8 | Examples of valid values: 9 |

10 |
    11 |
  • public void method(@Varargs String... args) { }
  • 12 |
  • public void method(@Varargs String[] args) { }
  • 13 |
  • public void method(@Varargs List<String> args) { }
  • 14 |
  • public void method(@Varargs Set<String> args) { }
  • 15 |
  • public void method(@Varargs Collection<String> args) { }
  • 16 |
17 |

18 | Examples of invalid values: 19 |

20 |
    21 |
  • public void method(@Varargs String args) { }
  • 22 |
  • public void method(@Varargs Integer args) { }
  • 23 |
  • public void method(@Varargs int args) { }
  • 24 |
25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/messages/LiteCommandsBundle.properties: -------------------------------------------------------------------------------- 1 | action.LiteCommands.CreateCommandClass.text=LiteCommands 2 | action.LiteCommands.CreateCommandClass.description=Creates new LiteCommands class --------------------------------------------------------------------------------