{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "stack": "android",
  "description": "Kotlin + Java code-graph rules. Adds what the graph needs on top of test-gap-rules/android.json, which already owns sourceExtensions, excludePathGlobs and the test-path predicates. Definition patterns here are deliberately broader than the test-gap publicApiPatterns: the graph wants internal types too, because Phase 1 narrows scope on the whole module, not just its public surface.",
  "comments": {
    "line": ["//"],
    "block": [["/*", "*/"]],
    "string": ["\"\"\"", "\""]
  },
  "definitionPatterns": [
    {
      "id": "enum",
      "kind": "enum",
      "regex": "\\benum\\s+(?:class\\s+)?([A-Z][A-Za-z0-9_]*)"
    },
    {
      "id": "record",
      "kind": "record",
      "regex": "\\brecord\\s+([A-Z][A-Za-z0-9_]*)"
    },
    {
      "id": "typealias",
      "kind": "typealias",
      "regex": "\\btypealias\\s+([A-Z][A-Za-z0-9_]*)"
    },
    {
      "id": "object",
      "kind": "object",
      "regex": "\\bobject\\s+([A-Z][A-Za-z0-9_]*)"
    },
    {
      "id": "interface",
      "kind": "interface",
      "regex": "\\binterface\\s+([A-Z][A-Za-z0-9_]*)"
    },
    {
      "id": "class",
      "kind": "class",
      "regex": "\\bclass\\s+([A-Z][A-Za-z0-9_]*)"
    },
    {
      "id": "fun",
      "kind": "fun",
      "regex": "\\bfun\\s+(?:<[^>]*>\\s*)?([a-zA-Z_][A-Za-z0-9_]*)"
    }
  ],
  "importPatterns": [
    {
      "id": "import",
      "regex": "^\\s*import\\s+(?:static\\s+)?(?:[A-Za-z_][A-Za-z0-9_]*\\.)+([A-Z][A-Za-z0-9_]*)"
    }
  ],
  "referenceKinds": ["class", "interface", "object", "enum", "record", "typealias"],
  "referenceKindsNote": "fun is deliberately absent, for the reason Swift's rules record for func: a bare lowercase name matched across files is almost never a call to that exact declaration, and on a large app the generic ones (invoke, build, create, get) take the top god-node slots purely because each happened to be declared once. Composables are the tempting exception - they are capitalised and behave like types - but they are declared with fun, so including them means including every other fun with them.",
  "ignoredIdentifiers": [
    "this",
    "super",
    "it",
    "init",
    "constructor",
    "companion",
    "class",
    "interface",
    "object",
    "enum",
    "record",
    "fun",
    "val",
    "var",
    "return",
    "when",
    "where",
    "is",
    "as",
    "in",
    "out",
    "by",
    "import",
    "package",
    "public",
    "private",
    "protected",
    "internal",
    "static",
    "final",
    "abstract",
    "open",
    "override",
    "sealed",
    "data",
    "inline",
    "suspend",
    "lateinit",
    "throws",
    "try",
    "catch",
    "finally",
    "null",
    "true",
    "false",
    "void",
    "int",
    "long",
    "boolean",
    "String",
    "Int",
    "Long",
    "Boolean",
    "Unit",
    "Any"
  ],
  "note": "Kotlin declaration modifiers are not separate patterns: `data class Foo`, `sealed class Foo` and `annotation class Foo` all still contain `class Foo`, so one pattern covers them. `enum` allows an optional `class` between keyword and name, which is the only shape that differs between Java (`enum Foo`) and Kotlin (`enum class Foo`). `object` matches the named form only - `companion object {` and the anonymous `object : Iface {` carry no name and correctly produce nothing. Imports are fully qualified on the JVM, so the pattern captures the final segment: `import com.example.ui.Button` resolves against the file named Button.kt, which is how the engine links a file-level import edge. A star import (`import com.example.ui.*`) captures nothing, deliberately - it names a package, and pointing every star import at an arbitrary file in that package would invent an edge nobody wrote. Pattern ORDER is load-bearing: `enum class Cabin` matches both the enum pattern and the class pattern, and the first match to register the name decides its kind, so the more specific patterns are listed first. With class first, every Kotlin enum was filed as a class and the report's symbol-kind census was wrong."
}
