Skip to content
/ Eligos Public

Eligos is a static code smell analysis tool for hybrid project of Kotlin and Java

License

Notifications You must be signed in to change notification settings

TnoAlex/Eligos

Repository files navigation

Eligos

GitHub License

Eligos, a static code analysis tool for the Kotlin programming language.

Support Code Smells

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.

Quick Start ...

  1. Clone this Repo
   git clone https://github.com/TnoAlex/Eligos.git
  1. 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
  1. Compiler & Build
    ./gradlew build #on linux 
    ./gradlew.bat build #on windows
  1. Find the libs You can find the executable cli jar at eligos-cli/build/libs and Installable plugin at eligos-plugin/build/distributions.

From Docker

  1. Clone this Repo

       git clone https://github.com/TnoAlex/Eligos.git
  2. Build Docker Image

    	docker build -t eligos:1.0 .
  3. 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.

Arguments & Options

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.

How to add more rules

We provide a simple mechanism to extend eligos. The following steps allow you to create a rule that belongs to you:

  1. Create a Psi file processor which implement PsiProcessor, and define a issue which is extend Issue

  2. 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)
  3. 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
        }
    }
  4. 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
        }
    }
  5. That's All😝. If you want to customize Eligos in more detail, please refer to the Eligos Architecture Diagram , Execution Process.