[Kotlin] Resolve FQNs for Definitions

Goal: 

Compute Fully Qualified Names (FQNs) for all definitions identified in Kotlin files.

This issue focuses on traversing the AST to determine the complete, unique, hierarchical name for each definition. This is crucial for linking nodes in the Knowledge Graph.

Scope:

The FQN resolution should correctly handle:

  • Package-level definitions: Based on package declaration and file path.
  • Nested classes/interfaces/objects: FQNs for inner classnested classcompanion object, and other nested declarations (e.g., com.example.MyClass.NestedClasscom.example.MyClass.Companion.myMethod).
  • Member functions and properties: FQNs for members within classes, interfaces, and objects.
  • Extension functions and properties: FQNs should reflect their declaration site (e.g., com.example.MyExtensions.myExtensionFunction). The receiver type should be included as metadata of the FQN.
  • Type aliases: FQNs for type aliases.

Implementation Details: 

This will involve a traversal of the AST (similar to build_fqn_and_node_indices in the Ruby parser MR gitlab-org/rust/gitlab-code-parser!1) to build a scope stack that tracks the current package, class, object, or function context. When a definition node is encountered, its FQN is constructed by combining the scope stack with its local name. The file path will be used to derive the initial package FQN segment if a package declaration is missing or incomplete.

Example Kotlin Code (from Issue 3.1):

package com.example.app

class MyClass(val id: Int) {
    fun memberFunction(param: String): Int { /* ... */ }
    companion object MyCompanion {
        fun staticMethod() {}
    }
}
fun String.myExtension(): String = this.reversed()
typealias Name = String

Expected FQNs for Definitions:

  • com.example.app.MyClass
  • com.example.app.MyClass.id
  • com.example.app.MyClass.memberFunction
  • com.example.app.MyClass.MyCompanion
  • com.example.app.MyClass.MyCompanion.staticMethod
  • com.example.app.myExtension (or a similar convention for extensions, e.g., com.example.app.<file_name>.String.myExtension)
  • com.example.app.Name

Out of scope:

  • For the first iteration, overloaded functions and constructors will share the same FQN.
Edited by Jean-Gabriel Doyon