Eligos, a static code analysis tool for the Kotlin programming language.
In the current version, we can detect the following 13 code smell:
Type | Label | Description |
Circular References | 🟨 | Two or more classes or files have interdependencies that form a closed loop |
Excessive Parameters | 🟨 | A method has too many arguments |
Unused Import | 🟨 | Classes, attributes, methods, or packages that have been imported into a file, but have never been used |
Complex Method | 🟨 | The complexity of the loop is too large |
Provide Immutable Collection | 🟩 | Kotlin provides immutable collection types when java calling Kotlin's API |
Internal Exposed | 🟩 | Java expose Kotlin internal declaration to public. |
Uncertain Nullable Platform Expression Usage | 🟩 | Kotlin locally calls a Java method that returns a null-agnostic type, and uses this result directly in a Kotlin method that expects completely non-null arguments |
Uncertain Nullable Platform Caller | 🟩 | Call a method or access a property whose caller expression type is platform type in Kotlin. |
Nullable Passed To Platform Parameter | 🟩 | Kotlin passed a nullable parameter to a Java method which takes platform parameter. |
Uncertain Nullable Platform Type In Property | 🟩 | Kotlin calls an empty agnostic Java method or property and uses this value as the return value of the getter for the class property |
Non JVMStatic Companion Function | 🟩 | Public functions in a companion object must be annotated with @JvmStatic to be exposed as a static method.Without the annotation, these functions are only available as instance methods on a static Companion field. |
Non JVMField Companion Value | 🟩 | Public, non-const properties which are effective constants in a companion object must be annotated with @JvmField to be exposed as a static field. |
Incomprehensible JavaFacade Name | 🟩 | When a file contains top-level functions or properties, always annotate it with @file:JvmName("Foo") to provide a nice name.By default, top-level members in a file MyClass.kt will end up in a class called MyClassKt which is unappealing and leaks the language as an implementation detail. |
Ignored Exception | 🟩 | Functions which can throw checked exceptions should document them with @Throws. Runtime exceptions should be documented in KDoc.Be mindful of the APIs a function delegates to as they may throw checked exceptions which Kotlin otherwise silently allows to propagate. |
When Instead Of Cascade If | 🟪 | If statements with too many cascades should be replaced with when statements |
Implicit Single Expression Function | 🟪 | kotlin's one-expression method returns a value of type other than Unit, but does not specify the return type |
Object Extends Throwable | 🟪 | The class decorated with kotlin object inherits from Throwable |
Optimized Tail Recursion | 🟪 | The tail recursion function in Kotlin does not indicate that it is tail recursive |
In the table, yellow is common to Java Kotlin, green is generated when Koltin Java calls each other, and purple is unique to Kotlin.
- Clone this Repo
git clone https://github.com/TnoAlex/Eligos.git
- Prepare the environment Gradle 6.8.3+ is the minimum requirement. However, the recommended versions together with the other tools recommended versions are:
Gradle | Kotlin | Java Target Level | JDK Min Version |
---|---|---|---|
8.0+ |
1.9.10 |
17 |
17 |
- Compiler & Build
./gradlew build #on linux
./gradlew.bat build #on windows
- Find the libs
You can find the executable cli jar at
eligos-cli/build/libs
and Installable plugin ateligos-plugin/build/distributions
.
-
Clone this Repo
git clone https://github.com/TnoAlex/Eligos.git
-
Build Docker Image
docker build -t eligos:1.0 .
-
Run Eligos by docker
docker run -v $PROJECT:/dist/project -v $RESULT:/dist/result eligos:1.0 kotlin ./project ./result --with java
In the above command,
$PRJECT
refers to the local location of the item to be analyzed,$RESULT
the location where the local results are stored,Make sure they are all present before using this command. The two folders located after the Kotlin parameter are the internal Docker mappings, which are fixed.
The CLI tool usage could be listed by eligos --help
, like following:
Usage: command-parser [<options>] <major language> <source path> [<result
output path>]
Options:
-w, --with=<text> Secondary languages that are analyzed in
collaboration with the primary language
-ecp, --class-path=<path> The classpath of the project to be analyzed.
(Default is source path and '.',If your project
has external jar dependencies, add the paths of
them)
-jh, --jdk-home=<path> The path of 'JAVA_HOME'. (Default is current jvm's
base dir)
-kv, --kotlin-v=<text> The version of kotlin in the project
-jt, --jvm-target=<text> The target of project's bytecode
-kl, --kotlin-lib=<path> The path of kotlin-std-lib. (Default is current
kotlin lib's path)
-p, --prefix=<text> The result file name prefix
-f, --format=(JSON|XML|HTML|TEXT)
The Presentation of results
-r, --rules=<path> Specify the rules to use
-D, --debug Out put exception stack
-Nr, --no-report Disable reporter (debug only)
-h, --help Show this message and exit
Arguments:
<major language> The major language to be analyzed
<source path> The path of source files
<result output path> The path to out put result
If yob use Third-party libraries, or use build tools like Maven
or Gradlle
, please set the correct classpath
so
that the tool can find these dependencies and avoid the problem that some external dependencies cannot be resolved.
We provide a simple mechanism to extend eligos. The following steps allow you to create a rule that belongs to you:
-
Create a Psi file processor which implement
PsiProcessor
, and define a issue which is extendIssue
-
Add an Psi file listener with
@EventListener
annotation and report the issue like this:class MyProcessor : PsiProcessor{ @EventLinster fun process(ktFile:PsiFile){ //do someting context.reportIssue(MyIssue(hashSetOf(ktFile.virtualFilePath))) } } class MyIssue(affectedFiles:HashSet<String>) : Issue(AnalysisHierarchyEnum.FILE, affectedFiles, "My Issue", null)
-
Make your rule can scaned by the Component Manager with
@Component
annotation like this@Component class MyProcessor : PsiProcessor{ @EventLinster fun process(ktFile:PsiFile){ //do someting } }
-
If you want this rule only run on plugin, please use
@Suitable
annotation@Component @Suitable(LaunchEnvironment.IDE_PLUGIN) class MyProcessor : PsiProcessor{ @EventLinster fun process(ktFile:PsiFile){ //do someting } }
-
That's All😝. If you want to customize Eligos in more detail, please refer to the Eligos Architecture Diagram , Execution Process.