mirror of
https://github.com/safishamsi/graphify.git
synced 2026-09-22 13:35:46 +00:00
fix(extract): filter Kotlin builtin/stdlib types from references graph
_kotlin_collect_type_refs had no equivalent of _JAVA_BUILTIN_TYPES / _PYTHON_ANNOTATION_NOISE / _GO_PREDECLARED_TYPES, so every Boolean/String/ Int/List/... type annotation in a .kt file became a real graph node/edge. Unrelated files sharing only these language-level types were getting merged into the same community by cluster-only. Add _KOTLIN_BUILTIN_TYPES (kotlin.* scalars, collections, throwables - deliberately not Android/JVM framework types like Context/View/Bundle, matching how _JAVA_BUILTIN_TYPES doesn't filter framework types either) and check it plus _JAVA_BUILTIN_TYPES (Kotlin freely references java.util.Date/UUID/etc) at the three call sites that previously appended unconditionally. Deliberately excludes "Result" from the filter list even though kotlin.Result exists - it collides with the very common user-defined sealed-class name (confirmed against this repo's own sample.kt fixture, which defines its own Result<T>). Verified on a ~400-file Android/Kotlin project: 3693->3239 nodes (-12%), 6481->5221 edges (-19%), with a previously merged 5-file grab-bag community cleanly splitting out an unrelated screen-dimension utility.
This commit is contained in:
@@ -607,6 +607,35 @@ def _php_method_return_type_node(method_node):
|
||||
return c
|
||||
return None
|
||||
|
||||
# Kotlin stdlib scalar/collection/core types that appear constantly as type
|
||||
# annotations but carry no useful semantic meaning as graph nodes (mirrors
|
||||
# _JAVA_BUILTIN_TYPES / _PYTHON_ANNOTATION_NOISE / _GO_PREDECLARED_TYPES).
|
||||
# Kotlin compiles to the JVM and freely references java.* types too, so this
|
||||
# is combined with _JAVA_BUILTIN_TYPES at the call site rather than duplicated.
|
||||
_KOTLIN_BUILTIN_TYPES = frozenset({
|
||||
# kotlin — scalars & core
|
||||
"Any", "Unit", "Nothing", "Boolean", "Byte", "Short", "Int", "Long",
|
||||
"Float", "Double", "Char", "String", "CharSequence", "Number",
|
||||
"Comparable", "Enum", "Annotation", "Pair", "Triple", "Lazy",
|
||||
"Function",
|
||||
# kotlin — throwables
|
||||
"Throwable", "Exception", "RuntimeException", "Error",
|
||||
"IllegalArgumentException", "IllegalStateException", "NullPointerException",
|
||||
"IndexOutOfBoundsException", "ClassCastException", "NumberFormatException",
|
||||
"ArithmeticException", "UnsupportedOperationException",
|
||||
"NoSuchElementException", "ConcurrentModificationException",
|
||||
"StackOverflowError", "OutOfMemoryError", "AssertionError",
|
||||
"InterruptedException",
|
||||
# kotlin.collections
|
||||
"Array", "List", "MutableList", "ArrayList", "Set", "MutableSet",
|
||||
"HashSet", "LinkedHashSet", "Map", "MutableMap", "HashMap",
|
||||
"LinkedHashMap", "Collection", "MutableCollection", "Iterable",
|
||||
"MutableIterable", "Iterator", "MutableIterator", "ListIterator",
|
||||
"MutableListIterator", "Sequence", "Comparator",
|
||||
# kotlin.text
|
||||
"Regex", "MatchResult", "StringBuilder",
|
||||
})
|
||||
|
||||
def _kotlin_user_type_name(user_type_node, source: bytes) -> str | None:
|
||||
"""Return the head identifier text from a Kotlin user_type node (without generics)."""
|
||||
if user_type_node is None:
|
||||
@@ -636,14 +665,14 @@ def _kotlin_collect_type_refs(node, source: bytes, generic: bool, out: list[tupl
|
||||
for c in node.children:
|
||||
if c.type in ("identifier", "type_identifier"):
|
||||
text = _read_text(c, source)
|
||||
if text:
|
||||
if text and text not in _KOTLIN_BUILTIN_TYPES and text not in _JAVA_BUILTIN_TYPES:
|
||||
out.append((text, "generic_arg" if generic else "type"))
|
||||
break
|
||||
if c.type == "simple_user_type":
|
||||
for sub in c.children:
|
||||
if sub.type in ("identifier", "type_identifier"):
|
||||
text = _read_text(sub, source)
|
||||
if text:
|
||||
if text and text not in _KOTLIN_BUILTIN_TYPES and text not in _JAVA_BUILTIN_TYPES:
|
||||
out.append((text, "generic_arg" if generic else "type"))
|
||||
break
|
||||
break
|
||||
@@ -659,7 +688,7 @@ def _kotlin_collect_type_refs(node, source: bytes, generic: bool, out: list[tupl
|
||||
return
|
||||
if t in ("identifier", "type_identifier"):
|
||||
text = _read_text(node, source)
|
||||
if text:
|
||||
if text and text not in _KOTLIN_BUILTIN_TYPES and text not in _JAVA_BUILTIN_TYPES:
|
||||
out.append((text, "generic_arg" if generic else "type"))
|
||||
return
|
||||
if t in ("nullable_type", "parenthesized_type", "type_reference"):
|
||||
|
||||
@@ -656,6 +656,27 @@ def test_kotlin_parameter_return_generic_and_field_contexts():
|
||||
assert ("run", "DataProcessor") in _edge_labels(r, "references", "generic_arg")
|
||||
assert ("DataProcessor", "Result") in _edge_labels(r, "references", "field")
|
||||
|
||||
def test_kotlin_builtin_types_not_emitted_as_references():
|
||||
# kotlin.* scalar/collection/core types used as parameter, return, or field
|
||||
# types carry no useful graph meaning: they never resolve to a project node,
|
||||
# so emitting `references` edges to them is pure noise (mirrors the Java
|
||||
# _JAVA_BUILTIN_TYPES / Python _PYTHON_ANNOTATION_NOISE handling).
|
||||
r = extract_kotlin(FIXTURES / "sample.kt")
|
||||
ref_targets = {target for (_, target) in _edge_labels(r, "references")}
|
||||
for builtin in ("String", "Int"):
|
||||
assert builtin not in ref_targets, (
|
||||
f"builtin type {builtin!r} should not be a references target"
|
||||
)
|
||||
|
||||
def test_kotlin_user_types_still_emit_references():
|
||||
# Guard against over-filtering: a user-defined class sharing its name with a
|
||||
# common domain-modeling identifier (Result) must still resolve to a real
|
||||
# edge - the builtin filter is a fixed name list, so it must stay narrow
|
||||
# enough not to swallow common user-chosen names like a sealed-class "Result".
|
||||
r = extract_kotlin(FIXTURES / "sample.kt")
|
||||
assert ("DataProcessor", "Result") in _edge_labels(r, "references", "field")
|
||||
assert ("run", "DataProcessor") in _edge_labels(r, "references", "parameter_type")
|
||||
|
||||
|
||||
# ── Scala ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user