adl-toolkit 0.0.0-stage → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL_TOOLKIT.md +163 -0
- package/README.md +269 -2
- package/adl_drift/__init__.py +6 -0
- package/adl_drift/cli/__init__.py +1 -0
- package/adl_drift/cli/commands.py +993 -0
- package/adl_drift/cli/main.py +744 -0
- package/adl_drift/cortex/__init__.py +1 -0
- package/adl_drift/cortex/embeddings.py +96 -0
- package/adl_drift/cortex/memory.py +1749 -0
- package/adl_drift/cortex/patterns.py +89 -0
- package/adl_drift/cortex/telemetry.py +192 -0
- package/adl_drift/detectors/__init__.py +1 -0
- package/adl_drift/detectors/async_patterns.py +115 -0
- package/adl_drift/detectors/base.py +121 -0
- package/adl_drift/detectors/config.py +122 -0
- package/adl_drift/detectors/data_access.py +128 -0
- package/adl_drift/detectors/decorators.py +122 -0
- package/adl_drift/detectors/dynamic_patterns.py +260 -0
- package/adl_drift/detectors/errors.py +134 -0
- package/adl_drift/detectors/imports.py +132 -0
- package/adl_drift/detectors/logging_patterns.py +108 -0
- package/adl_drift/detectors/routes.py +257 -0
- package/adl_drift/detectors/security.py +236 -0
- package/adl_drift/detectors/taint.py +406 -0
- package/adl_drift/detectors/tests.py +95 -0
- package/adl_drift/detectors/type_conventions.py +81 -0
- package/adl_drift/graph/__init__.py +1 -0
- package/adl_drift/graph/builder.py +2670 -0
- package/adl_drift/graph/cfg.py +461 -0
- package/adl_drift/graph/cluster.py +40 -0
- package/adl_drift/graph/edges.py +86 -0
- package/adl_drift/graph/node.py +90 -0
- package/adl_drift/harness/__init__.py +10 -0
- package/adl_drift/harness/setup.py +832 -0
- package/adl_drift/harness/skills/adl-drift.md +25 -0
- package/adl_drift/harness/skills/drift-antigravity.md +19 -0
- package/adl_drift/harness/skills/drift-generic.md +19 -0
- package/adl_drift/harness/watch.py +84 -0
- package/adl_drift/lang/__init__.py +8 -0
- package/adl_drift/lang/base.py +464 -0
- package/adl_drift/lang/java/__init__.py +6 -0
- package/adl_drift/lang/java/backend.py +97 -0
- package/adl_drift/lang/java/cfg.py +1424 -0
- package/adl_drift/lang/java/config.py +707 -0
- package/adl_drift/lang/java/detectors/__init__.py +29 -0
- package/adl_drift/lang/java/detectors/additional.py +445 -0
- package/adl_drift/lang/java/detectors/base.py +154 -0
- package/adl_drift/lang/java/detectors/data_access.py +148 -0
- package/adl_drift/lang/java/detectors/imports.py +53 -0
- package/adl_drift/lang/java/detectors/routes.py +159 -0
- package/adl_drift/lang/java/detectors/security.py +386 -0
- package/adl_drift/lang/java/detectors/tests.py +74 -0
- package/adl_drift/lang/java/extractor.py +582 -0
- package/adl_drift/lang/java/ids.py +99 -0
- package/adl_drift/lang/java/parser.py +49 -0
- package/adl_drift/lang/java/resolution/__init__.py +1 -0
- package/adl_drift/lang/java/resolution/constants.py +1619 -0
- package/adl_drift/lang/java/resolution/constructors.py +278 -0
- package/adl_drift/lang/java/resolution/context.py +305 -0
- package/adl_drift/lang/java/resolution/dispatch.py +540 -0
- package/adl_drift/lang/java/resolution/functional.py +1318 -0
- package/adl_drift/lang/java/resolution/generated.py +95 -0
- package/adl_drift/lang/java/resolution/model.py +153 -0
- package/adl_drift/lang/java/resolution/orchestration.py +866 -0
- package/adl_drift/lang/java/resolution/overloads.py +1275 -0
- package/adl_drift/lang/java/resolution/scopes.py +1111 -0
- package/adl_drift/lang/java/resolution/types.py +2947 -0
- package/adl_drift/lang/java/resolver.py +1401 -0
- package/adl_drift/lang/java/scopes.py +69 -0
- package/adl_drift/lang/java/taint.py +500 -0
- package/adl_drift/lang/java/type_provenance.py +342 -0
- package/adl_drift/lang/python/__init__.py +8 -0
- package/adl_drift/lang/python/backend.py +94 -0
- package/adl_drift/lang/python/cfg.py +537 -0
- package/adl_drift/lang/python/extractor.py +454 -0
- package/adl_drift/lang/python/parser.py +41 -0
- package/adl_drift/lang/python/resolver.py +1789 -0
- package/adl_drift/lang/python/taint.py +365 -0
- package/adl_drift/lang/registry.py +117 -0
- package/adl_drift/parser/__init__.py +1 -0
- package/adl_drift/parser/cache.py +38 -0
- package/adl_drift/parser/core.py +33 -0
- package/adl_drift/parser/extractor.py +17 -0
- package/adl_drift/parser/literal_eval.py +326 -0
- package/adl_drift/scanner/__init__.py +1 -0
- package/adl_drift/scanner/discovery.py +338 -0
- package/adl_drift/scanner/incremental.py +261 -0
- package/adl_drift/scanner/parallel.py +224 -0
- package/adl_drift/server/__init__.py +1 -0
- package/adl_drift/server/handlers.py +2849 -0
- package/adl_drift/server/mcp_server.py +127 -0
- package/adl_drift/server/mcp_stdio.py +335 -0
- package/adl_drift/server/protocol.py +71 -0
- package/adl_drift/server/static/index.html +696 -0
- package/adl_drift/server/web.py +350 -0
- package/adl_drift/utils/__init__.py +1 -0
- package/adl_drift/utils/config.py +77 -0
- package/adl_drift/utils/fswalk.py +52 -0
- package/adl_drift/utils/types.py +345 -0
- package/bin/adl-drift.mjs +35 -0
- package/bin/adl-toolkit.mjs +488 -0
- package/package.json +29 -4
- package/pyproject.toml +49 -0
- package/scripts/install_toolkit.py +3584 -0
|
@@ -0,0 +1,1619 @@
|
|
|
1
|
+
"""Policy tables and exact external facts used by Java call resolution."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from typing import Dict, FrozenSet, List, Set, Tuple, Union
|
|
7
|
+
|
|
8
|
+
from adl_drift.lang.java.scopes import TYPE_BODIES
|
|
9
|
+
|
|
10
|
+
# P2.7-equivalent deny-list for Java: `java.lang.Object` methods (present on
|
|
11
|
+
# every instance whether declared or not) + common Collection/Map/Iterator
|
|
12
|
+
# method names. Unlike Python's `PYTHON_BUILTINS` (which also guards a
|
|
13
|
+
# whole-project unique-simple-name fallback that Java's call resolver has no
|
|
14
|
+
# equivalent of), `JavaCallResolver` no longer consults this set at all for
|
|
15
|
+
# call resolution — own-class and ancestor lookup are both fully structural
|
|
16
|
+
# (real CONTAINS/INHERITS/IMPLEMENTS edges, never a guess), so gating either
|
|
17
|
+
# of them here only cost recall for zero precision benefit (P4.4 regression
|
|
18
|
+
# fix; `_resolve_own_or_ancestor` used to early-return unresolved whenever
|
|
19
|
+
# the receiver's own class didn't declare a denied name itself, even when an
|
|
20
|
+
# ancestor genuinely did). `JAVA_BUILTINS` still backs
|
|
21
|
+
# `ResolverConfig.builtins_deny_list`, consumed by
|
|
22
|
+
# `CallGraphBuilder._is_denied()` for the language-agnostic `god_nodes()`
|
|
23
|
+
# metric — that usage is unrelated to call resolution and unaffected here.
|
|
24
|
+
JAVA_OBJECT_METHODS: Set[str] = {
|
|
25
|
+
"equals", "hashCode", "toString", "getClass", "clone", "finalize",
|
|
26
|
+
"notify", "notifyAll", "wait",
|
|
27
|
+
}
|
|
28
|
+
JAVA_COMMON_COLLECTION_METHODS: Set[str] = {
|
|
29
|
+
"get", "set", "add", "remove", "size", "isEmpty", "contains", "clear",
|
|
30
|
+
"put", "putAll", "containsKey", "containsValue", "keySet", "values",
|
|
31
|
+
"entrySet", "iterator", "next", "hasNext", "forEach", "stream",
|
|
32
|
+
"toArray", "addAll", "removeAll", "retainAll", "indexOf", "sort",
|
|
33
|
+
"getOrDefault", "compute", "computeIfAbsent", "computeIfPresent",
|
|
34
|
+
"merge", "of", "asList", "peek", "poll", "push", "pop", "offer",
|
|
35
|
+
}
|
|
36
|
+
JAVA_BUILTINS: Set[str] = JAVA_OBJECT_METHODS | JAVA_COMMON_COLLECTION_METHODS
|
|
37
|
+
|
|
38
|
+
# Lombok-style annotation simple name -> name *prefixes* it generates on the
|
|
39
|
+
# annotated class. Illustrative, not exhaustive — the Java analogue of
|
|
40
|
+
# DECORATOR_STUB_TABLE, scoped to "simple proxies" per this issue; Spring
|
|
41
|
+
# AOP/DI dispatch is P4.12, not here.
|
|
42
|
+
JAVA_ANNOTATION_STUB_TABLE: Dict[str, FrozenSet[str]] = {
|
|
43
|
+
"Getter": frozenset({"get", "is"}),
|
|
44
|
+
"Setter": frozenset({"set"}),
|
|
45
|
+
"Data": frozenset({"get", "is", "set", "toString", "hashCode", "equals", "canEqual"}),
|
|
46
|
+
"Value": frozenset({"get", "is", "toString", "hashCode", "equals", "canEqual"}),
|
|
47
|
+
"Builder": frozenset({"build", "builder", "toBuilder"}),
|
|
48
|
+
"EqualsAndHashCode": frozenset({"equals", "hashCode", "canEqual"}),
|
|
49
|
+
"ToString": frozenset({"toString"}),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
# argument_list / formal_parameters punctuation children to skip when
|
|
53
|
+
# counting/walking positional entries.
|
|
54
|
+
_PUNCTUATION = (",", "(", ")")
|
|
55
|
+
|
|
56
|
+
# Tree-sitter keeps comments as *named* children of `argument_list`
|
|
57
|
+
# (`line_comment` / `block_comment`), so `call(a, // note\n b)` has three
|
|
58
|
+
# named children but two arguments. Punctuation is unnamed; comments are
|
|
59
|
+
# named trivia. Every positional walk over an argument list must go through
|
|
60
|
+
# here so arity and per-argument typing never disagree.
|
|
61
|
+
_COMMENT_CST_TYPES = frozenset({"line_comment", "block_comment", "comment"})
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def argument_nodes(args_node) -> list:
|
|
65
|
+
"""Positional argument expressions of an `argument_list` node, in order,
|
|
66
|
+
skipping punctuation and comment trivia. `None` -> `[]`."""
|
|
67
|
+
if args_node is None:
|
|
68
|
+
return []
|
|
69
|
+
return [
|
|
70
|
+
child for child in args_node.children
|
|
71
|
+
if child.is_named and child.type not in _COMMENT_CST_TYPES
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
_LITERAL_ARG_TYPE = {
|
|
75
|
+
"character_literal": "char",
|
|
76
|
+
"string_literal": "String",
|
|
77
|
+
"true": "boolean",
|
|
78
|
+
"false": "boolean",
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
# Sentinel "type" for the `null` literal. `null` is a Java keyword, so no real
|
|
82
|
+
# type is ever named `null` and this cannot collide with a declared type. It
|
|
83
|
+
# carries the JLS "null type": assignable to every *reference* type (class,
|
|
84
|
+
# interface, array, boxed primitive), never to a primitive. Treated as a
|
|
85
|
+
# *known* argument type by overload selection (not "unknown"), so `save(null)`
|
|
86
|
+
# runs through most-specific ranking among reference candidates instead of
|
|
87
|
+
# fanning out across every arity match — see `_types_compatible`.
|
|
88
|
+
_NULL_ARG_TYPE = "null"
|
|
89
|
+
# Must survive `erased_type()` unchanged. Angle-bracket sentinels are invalid
|
|
90
|
+
# here because erasure correctly treats them as a generic argument list and
|
|
91
|
+
# reduces the value to an empty type.
|
|
92
|
+
_LAMBDA_ARG_TYPE = "$drift_lambda$"
|
|
93
|
+
# Placeholder for one argument position whose type genuinely cannot be
|
|
94
|
+
# determined (an external/JDK method-call result with no exact-return fact,
|
|
95
|
+
# for example). Unlike `_NULL_ARG_TYPE`/`_LAMBDA_ARG_TYPE` — both real,
|
|
96
|
+
# *known* facts about the argument — this means "no information," so
|
|
97
|
+
# `_types_compatible` treats it as compatible with every parameter shape
|
|
98
|
+
# rather than ruling anything in or out. It lets a mixed argument list (some
|
|
99
|
+
# positions known, one unresolvable) still exclude a candidate that is
|
|
100
|
+
# provably incompatible on a position that *is* known, without ever
|
|
101
|
+
# guessing the unresolvable one. See `_narrow_candidates_by_known_arg_types`.
|
|
102
|
+
_UNKNOWN_ARG_TYPE = "$drift_unknown$"
|
|
103
|
+
# Marks a local variable initialized from a Mockito `mock(...)`/`spy(...)`
|
|
104
|
+
# factory call (see `ScopeInferenceMixin._is_mockito_factory_call`). Stored
|
|
105
|
+
# through the same allocation-tracking path as a real `new Impl()` so
|
|
106
|
+
# `_abstract_fan_out`'s allocation-narrowing step can recognize it and
|
|
107
|
+
# decline to fan out at all — a mock has no real declared implementation to
|
|
108
|
+
# dispatch to, so guessing any concrete implementor (unrelated project code
|
|
109
|
+
# that happens to declare the same interface method) is a wrong edge every
|
|
110
|
+
# stubbed call site, not an unresolved one.
|
|
111
|
+
_MOCK_ALLOCATION_TYPE = "$drift_mock$"
|
|
112
|
+
_JAVA_FUNCTIONAL_INTERFACES: FrozenSet[str] = frozenset({
|
|
113
|
+
"BooleanSupplier", "Callable", "Comparator", "Consumer", "BiConsumer", "Function",
|
|
114
|
+
"BiFunction", "Predicate", "BiPredicate", "Supplier", "Runnable",
|
|
115
|
+
"UnaryOperator", "BinaryOperator",
|
|
116
|
+
})
|
|
117
|
+
# (abstract-method arity, is-void-returning) for each JDK functional
|
|
118
|
+
# interface above. Used only to narrow a lambda-expression argument's
|
|
119
|
+
# candidate overloads by two syntactic, JLS-exact facts about the lambda
|
|
120
|
+
# itself — its own declared parameter count, and (for a block body) whether
|
|
121
|
+
# it contains a `return <expr>;` — against a *sibling* candidate's SAM shape
|
|
122
|
+
# (E1, JAVA_METRICS_SPRING_MODULITH_PRECISION_SAMPLE.md:
|
|
123
|
+
# `Scenario.stimulate(Runnable/Supplier/Function/BiConsumer/BiFunction)` all
|
|
124
|
+
# accepted any lambda regardless of its own arity/return shape). Excludes
|
|
125
|
+
# `Comparator`/`BiPredicate` from the shape table entries that would collide
|
|
126
|
+
# with `Function`/`BiFunction`'s arity on purpose: `Comparator` and
|
|
127
|
+
# `BiFunction` are both arity-2/non-void, so they are never distinguishable
|
|
128
|
+
# by shape alone anyway; leaving both in the table changes nothing since
|
|
129
|
+
# neither ever gets excluded from the other.
|
|
130
|
+
_JAVA_FUNCTIONAL_INTERFACE_SHAPE: Dict[str, Tuple[int, bool]] = {
|
|
131
|
+
"BooleanSupplier": (0, False),
|
|
132
|
+
"Callable": (0, False),
|
|
133
|
+
"Comparator": (2, False),
|
|
134
|
+
"Consumer": (1, True),
|
|
135
|
+
"BiConsumer": (2, True),
|
|
136
|
+
"Function": (1, False),
|
|
137
|
+
"BiFunction": (2, False),
|
|
138
|
+
"Predicate": (1, False),
|
|
139
|
+
"BiPredicate": (2, False),
|
|
140
|
+
"Supplier": (0, False),
|
|
141
|
+
"Runnable": (0, True),
|
|
142
|
+
"UnaryOperator": (1, False),
|
|
143
|
+
"BinaryOperator": (2, False),
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Integer/floating-point literal node types whose Java type depends on a
|
|
147
|
+
# suffix character in the literal *text*, not just the node type (a
|
|
148
|
+
# `decimal_integer_literal` is `int` by default but `long` when it ends in
|
|
149
|
+
# `l`/`L`; a `decimal_floating_point_literal` is `double` by default but
|
|
150
|
+
# `float` when it ends in `f`/`F` — JLS 3.10.1/3.10.2). Same rule applies to
|
|
151
|
+
# hex/octal/binary integer literals.
|
|
152
|
+
_INTEGER_LITERAL_TYPES = frozenset({
|
|
153
|
+
"decimal_integer_literal", "hex_integer_literal",
|
|
154
|
+
"octal_integer_literal", "binary_integer_literal",
|
|
155
|
+
})
|
|
156
|
+
_FLOATING_POINT_LITERAL_TYPES = frozenset({
|
|
157
|
+
"decimal_floating_point_literal", "hex_floating_point_literal",
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
# The CST node types that carry a caller body `resolve_calls` must walk:
|
|
161
|
+
# regular methods, ordinary constructors, and a `record`'s *compact*
|
|
162
|
+
# canonical constructor (`R { ... }`) — the last has a real body whose call
|
|
163
|
+
# sites would otherwise be dropped (it is a distinct node type from
|
|
164
|
+
# `constructor_declaration`). Shared by `_iter_method_cst` (what to yield as
|
|
165
|
+
# a caller) and `_NESTED_SCOPE_BOUNDARY` (where a body walk must stop
|
|
166
|
+
# descending) so the two never drift; `JavaSymbolExtractor._CONSTRUCTOR_TYPES`
|
|
167
|
+
# is the extractor-side counterpart that emits the matching FUNCTION nodes.
|
|
168
|
+
_METHOD_CST_TYPES = (
|
|
169
|
+
"method_declaration", "constructor_declaration", "compact_constructor_declaration",
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Node types whose call sites belong to a *different* enclosing method than
|
|
173
|
+
# whatever body we're currently walking — mirrors Python's "don't descend
|
|
174
|
+
# into nested function_definition" guard in `_collect_calls`. Java can't
|
|
175
|
+
# nest a method inside a method, but a method body can contain a local or
|
|
176
|
+
# anonymous class with its own `method_declaration`(s); those get their own
|
|
177
|
+
# top-level pass in `_iter_method_cst`; a type-body boundary marks where
|
|
178
|
+
# nested-class call sites start belonging to that class's own methods. Uses
|
|
179
|
+
# `scopes.TYPE_BODIES`, not just `class_body` — tree-sitter-java pairs
|
|
180
|
+
# `interface_declaration`/`enum_declaration`/`annotation_type_declaration`
|
|
181
|
+
# with their own `interface_body`/`enum_body`/`annotation_type_body`, so a
|
|
182
|
+
# `class_body`-only check walks straight through a local enum's `static {
|
|
183
|
+
# }` initializer or an interface constant's field initializer and
|
|
184
|
+
# misattributes its call sites to the enclosing method (PROBLEMS.md P4.6;
|
|
185
|
+
# same bug fixed in `lang/java/taint.py::_NESTED_SCOPE_BOUNDARY`, confirmed
|
|
186
|
+
# live via a spurious `CALLS` edge before this fix).
|
|
187
|
+
_NESTED_SCOPE_BOUNDARY = (*_METHOD_CST_TYPES, *TYPE_BODIES)
|
|
188
|
+
|
|
189
|
+
# Direct-parent node types of a bare instance-initializer `{ }` block (JLS
|
|
190
|
+
# 8.6) — i.e. every `TYPE_BODIES` container *except* that an enum's constant
|
|
191
|
+
# list wraps its trailing member section (fields, initializer blocks,
|
|
192
|
+
# methods) in an extra `enum_body_declarations` node tree-sitter-java uses
|
|
193
|
+
# nowhere else, so `block.parent.type` there is `enum_body_declarations`,
|
|
194
|
+
# not `enum_body` itself. Used by `_iter_initializer_sites` (below) to tell
|
|
195
|
+
# a real instance-initializer block apart from an ordinary nested `{ }`
|
|
196
|
+
# inside a method/constructor body (whose parent is never one of these
|
|
197
|
+
# types) without walking further up.
|
|
198
|
+
_INIT_BLOCK_PARENTS = TYPE_BODIES | {"enum_body_declarations"}
|
|
199
|
+
|
|
200
|
+
# JDK functional interfaces whose SAM parameter types are derivable without
|
|
201
|
+
# indexing JDK sources. Integers reference the interface's generic arguments;
|
|
202
|
+
# strings are concrete primitive types. Custom interfaces use graph metadata
|
|
203
|
+
# and the same generic-substitution path as normal Java calls.
|
|
204
|
+
_JDK_SAM_PARAMS: Dict[str, Tuple[Union[int, str], ...]] = {
|
|
205
|
+
"Runnable": (), "Callable": (), "Supplier": (), "BooleanSupplier": (),
|
|
206
|
+
"IntSupplier": (), "LongSupplier": (), "DoubleSupplier": (),
|
|
207
|
+
"Consumer": (0,), "Function": (0,), "Predicate": (0,), "UnaryOperator": (0,),
|
|
208
|
+
"BiConsumer": (0, 1), "BiFunction": (0, 1), "BiPredicate": (0, 1),
|
|
209
|
+
"BinaryOperator": (0, 0), "Comparator": (0, 0),
|
|
210
|
+
"IntConsumer": ("int",), "LongConsumer": ("long",),
|
|
211
|
+
"DoubleConsumer": ("double",), "IntFunction": ("int",),
|
|
212
|
+
"LongFunction": ("long",), "DoubleFunction": ("double",),
|
|
213
|
+
"IntPredicate": ("int",), "LongPredicate": ("long",),
|
|
214
|
+
"DoublePredicate": ("double",), "IntUnaryOperator": ("int",),
|
|
215
|
+
"LongUnaryOperator": ("long",), "DoubleUnaryOperator": ("double",),
|
|
216
|
+
"IntBinaryOperator": ("int", "int"),
|
|
217
|
+
"LongBinaryOperator": ("long", "long"),
|
|
218
|
+
"DoubleBinaryOperator": ("double", "double"),
|
|
219
|
+
"ToIntFunction": (0,), "ToLongFunction": (0,), "ToDoubleFunction": (0,),
|
|
220
|
+
"ToIntBiFunction": (0, 1), "ToLongBiFunction": (0, 1),
|
|
221
|
+
"ToDoubleBiFunction": (0, 1), "ObjIntConsumer": (0, "int"),
|
|
222
|
+
"ObjLongConsumer": (0, "long"), "ObjDoubleConsumer": (0, "double"),
|
|
223
|
+
"IntToLongFunction": ("int",), "IntToDoubleFunction": ("int",),
|
|
224
|
+
"LongToIntFunction": ("long",), "LongToDoubleFunction": ("long",),
|
|
225
|
+
"DoubleToIntFunction": ("double",), "DoubleToLongFunction": ("double",),
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
_JDK_SAM_RETURNS: Dict[str, Union[int, str]] = {
|
|
229
|
+
"Runnable": "void", "Callable": 0, "Supplier": 0,
|
|
230
|
+
"BooleanSupplier": "boolean", "IntSupplier": "int",
|
|
231
|
+
"LongSupplier": "long", "DoubleSupplier": "double",
|
|
232
|
+
"Consumer": "void", "BiConsumer": "void", "Function": 1,
|
|
233
|
+
"BiFunction": 2, "Predicate": "boolean", "BiPredicate": "boolean",
|
|
234
|
+
"UnaryOperator": 0, "BinaryOperator": 0, "Comparator": "int",
|
|
235
|
+
"IntConsumer": "void", "LongConsumer": "void", "DoubleConsumer": "void",
|
|
236
|
+
"IntFunction": 0, "LongFunction": 0, "DoubleFunction": 0,
|
|
237
|
+
"IntPredicate": "boolean", "LongPredicate": "boolean", "DoublePredicate": "boolean",
|
|
238
|
+
"IntUnaryOperator": "int", "LongUnaryOperator": "long", "DoubleUnaryOperator": "double",
|
|
239
|
+
"IntBinaryOperator": "int", "LongBinaryOperator": "long", "DoubleBinaryOperator": "double",
|
|
240
|
+
"ToIntFunction": "int", "ToLongFunction": "long", "ToDoubleFunction": "double",
|
|
241
|
+
"ToIntBiFunction": "int", "ToLongBiFunction": "long", "ToDoubleBiFunction": "double",
|
|
242
|
+
"ObjIntConsumer": "void", "ObjLongConsumer": "void", "ObjDoubleConsumer": "void",
|
|
243
|
+
"IntToLongFunction": "long", "IntToDoubleFunction": "double",
|
|
244
|
+
"LongToIntFunction": "int", "LongToDoubleFunction": "double",
|
|
245
|
+
"DoubleToIntFunction": "int", "DoubleToLongFunction": "long",
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# Type-declaration CST node kinds that can enclose a nested `@interface`
|
|
250
|
+
# (F-01 fix). Mirrors `JavaSymbolExtractor._CLASS_TYPES` plus
|
|
251
|
+
# `annotation_type_declaration` itself (an annotation type may nest inside
|
|
252
|
+
# another one), kept as a local copy rather than importing the extractor's
|
|
253
|
+
# constant — `_collect_annotation_type_names` walks raw CST nodes the
|
|
254
|
+
# extractor never turns into `Symbol`s, so the two have no shared id/scope
|
|
255
|
+
# logic to drift apart, only this grammar-level type list.
|
|
256
|
+
_ENCLOSING_TYPE_CST_TYPES = (
|
|
257
|
+
"class_declaration",
|
|
258
|
+
"interface_declaration",
|
|
259
|
+
"enum_declaration",
|
|
260
|
+
"record_declaration",
|
|
261
|
+
"annotation_type_declaration",
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# ---------------------------------------------------------------- P4.12 fan-out
|
|
265
|
+
# Annotation simple names (see codegraph-java-deep-dive.md §7.3) that mark a
|
|
266
|
+
# field for dependency injection — a receiver typed as an interface but read
|
|
267
|
+
# off such a field has its concrete bean chosen by the Spring container, so DI
|
|
268
|
+
# narrowing (below) can resolve it precisely where a bare interface receiver
|
|
269
|
+
# only fans out.
|
|
270
|
+
JAVA_INJECTION_ANNOTATIONS: FrozenSet[str] = frozenset({
|
|
271
|
+
"Autowired", "Inject", "Resource",
|
|
272
|
+
})
|
|
273
|
+
# Annotation simple names that register a class as a Spring bean (a concrete
|
|
274
|
+
# injectable candidate for any interface it implements).
|
|
275
|
+
JAVA_COMPONENT_ANNOTATIONS: FrozenSet[str] = frozenset({
|
|
276
|
+
"Component", "Service", "Repository", "Controller", "RestController",
|
|
277
|
+
})
|
|
278
|
+
JAVA_DI_ANNOTATION_FQNS: FrozenSet[str] = frozenset({
|
|
279
|
+
"org.springframework.beans.factory.annotation.Autowired",
|
|
280
|
+
"org.springframework.beans.factory.annotation.Qualifier",
|
|
281
|
+
"org.springframework.context.annotation.Bean",
|
|
282
|
+
"org.springframework.context.annotation.Primary",
|
|
283
|
+
"org.springframework.stereotype.Component",
|
|
284
|
+
"org.springframework.stereotype.Controller",
|
|
285
|
+
"org.springframework.stereotype.Repository",
|
|
286
|
+
"org.springframework.stereotype.Service",
|
|
287
|
+
"org.springframework.web.bind.annotation.RestController",
|
|
288
|
+
"jakarta.inject.Inject",
|
|
289
|
+
"jakarta.inject.Qualifier",
|
|
290
|
+
"jakarta.annotation.Resource",
|
|
291
|
+
"javax.inject.Inject",
|
|
292
|
+
"javax.inject.Qualifier",
|
|
293
|
+
"javax.annotation.Resource",
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
# Generic method signatures for JDK/container types whose source declaration is
|
|
297
|
+
# outside the analyzed project. Values are declared return types in terms of the
|
|
298
|
+
# receiver's class type parameters; source classes use the same substitution
|
|
299
|
+
# path via `_generic_return_type_from_source_method`.
|
|
300
|
+
JAVA_GENERIC_METHOD_STUB_RETURNS: Dict[Tuple[str, str], str] = {
|
|
301
|
+
# `java.lang.String` instance members whose declared return is the same
|
|
302
|
+
# across *every* overload (JDK 17+ javadoc). Only such fixed-return
|
|
303
|
+
# members belong here: a member with overload-dependent returns would
|
|
304
|
+
# turn a narrowing hint into a guess. Needed so a `String`-typed chain
|
|
305
|
+
# used as a call argument (`"...".formatted(a, b)`, `name.toUpperCase()`,
|
|
306
|
+
# `text.substring(1)`) can exclude a same-arity `Supplier<String>`/
|
|
307
|
+
# primitive sibling overload instead of fanning out at 0.55 (JUnit5
|
|
308
|
+
# FP/FN catalog #16476 and the wider `overload/java_resolver@0.55`
|
|
309
|
+
# stratum).
|
|
310
|
+
("String", "trim"): "String",
|
|
311
|
+
("String", "strip"): "String",
|
|
312
|
+
("String", "stripLeading"): "String",
|
|
313
|
+
("String", "stripTrailing"): "String",
|
|
314
|
+
("String", "stripIndent"): "String",
|
|
315
|
+
("String", "formatted"): "String",
|
|
316
|
+
("String", "toUpperCase"): "String",
|
|
317
|
+
("String", "toLowerCase"): "String",
|
|
318
|
+
("String", "substring"): "String",
|
|
319
|
+
("String", "replace"): "String",
|
|
320
|
+
("String", "replaceAll"): "String",
|
|
321
|
+
("String", "replaceFirst"): "String",
|
|
322
|
+
("String", "concat"): "String",
|
|
323
|
+
("String", "repeat"): "String",
|
|
324
|
+
("String", "intern"): "String",
|
|
325
|
+
("String", "indent"): "String",
|
|
326
|
+
("String", "translateEscapes"): "String",
|
|
327
|
+
("String", "length"): "int",
|
|
328
|
+
("String", "indexOf"): "int",
|
|
329
|
+
("String", "lastIndexOf"): "int",
|
|
330
|
+
("String", "compareTo"): "int",
|
|
331
|
+
("String", "compareToIgnoreCase"): "int",
|
|
332
|
+
("String", "codePointAt"): "int",
|
|
333
|
+
("String", "charAt"): "char",
|
|
334
|
+
("String", "isEmpty"): "boolean",
|
|
335
|
+
("String", "isBlank"): "boolean",
|
|
336
|
+
("String", "contains"): "boolean",
|
|
337
|
+
("String", "startsWith"): "boolean",
|
|
338
|
+
("String", "endsWith"): "boolean",
|
|
339
|
+
("String", "equals"): "boolean",
|
|
340
|
+
("String", "equalsIgnoreCase"): "boolean",
|
|
341
|
+
("String", "contentEquals"): "boolean",
|
|
342
|
+
("String", "matches"): "boolean",
|
|
343
|
+
("String", "regionMatches"): "boolean",
|
|
344
|
+
("String", "toCharArray"): "char[]",
|
|
345
|
+
("String", "getBytes"): "byte[]",
|
|
346
|
+
("String", "split"): "String[]",
|
|
347
|
+
("String", "lines"): "Stream<String>",
|
|
348
|
+
("String", "chars"): "IntStream",
|
|
349
|
+
("Class", "getClassLoader"): "ClassLoader",
|
|
350
|
+
("Class", "getName"): "String",
|
|
351
|
+
("Class", "getSimpleName"): "String",
|
|
352
|
+
("Class", "getPackage"): "java.lang.Package",
|
|
353
|
+
("Class", "getDeclaredMethod"): "java.lang.reflect.Method",
|
|
354
|
+
("Package", "getName"): "String",
|
|
355
|
+
("Method", "getName"): "String",
|
|
356
|
+
("Method", "getParameterTypes"): "Class[]",
|
|
357
|
+
("Iterable", "iterator"): "Iterator<T>",
|
|
358
|
+
("Collection", "iterator"): "Iterator<E>",
|
|
359
|
+
("List", "iterator"): "Iterator<E>",
|
|
360
|
+
("ArrayList", "iterator"): "Iterator<E>",
|
|
361
|
+
("LinkedList", "iterator"): "Iterator<E>",
|
|
362
|
+
("Collection", "stream"): "Stream<E>",
|
|
363
|
+
("List", "stream"): "Stream<E>",
|
|
364
|
+
("ArrayList", "stream"): "Stream<E>",
|
|
365
|
+
("LinkedList", "stream"): "Stream<E>",
|
|
366
|
+
("Set", "stream"): "Stream<E>",
|
|
367
|
+
("SortedSet", "stream"): "Stream<E>",
|
|
368
|
+
("Collection", "parallelStream"): "Stream<E>",
|
|
369
|
+
("List", "parallelStream"): "Stream<E>",
|
|
370
|
+
("Set", "parallelStream"): "Stream<E>",
|
|
371
|
+
("Iterator", "next"): "T",
|
|
372
|
+
("ListIterator", "next"): "E",
|
|
373
|
+
("List", "get"): "E",
|
|
374
|
+
# Java 21 SequencedCollection API. A declared List receiver retains its
|
|
375
|
+
# element type through `getFirst()` just as it does through indexed get.
|
|
376
|
+
("List", "getFirst"): "E",
|
|
377
|
+
("ArrayList", "get"): "E",
|
|
378
|
+
("ArrayList", "getFirst"): "E",
|
|
379
|
+
("LinkedList", "get"): "E",
|
|
380
|
+
("LinkedList", "getFirst"): "E",
|
|
381
|
+
("Optional", "get"): "T",
|
|
382
|
+
("Optional", "orElseThrow"): "T",
|
|
383
|
+
("Map", "get"): "V",
|
|
384
|
+
("Map", "getOrDefault"): "V",
|
|
385
|
+
("Map", "values"): "Collection<V>",
|
|
386
|
+
("Map", "keySet"): "Set<K>",
|
|
387
|
+
("Map", "entrySet"): "Set<Map.Entry<K,V>>",
|
|
388
|
+
("Entry", "getKey"): "K",
|
|
389
|
+
("Entry", "getValue"): "V",
|
|
390
|
+
("HashMap", "get"): "V",
|
|
391
|
+
("HashMap", "values"): "Collection<V>",
|
|
392
|
+
("HashMap", "keySet"): "Set<K>",
|
|
393
|
+
("HashMap", "entrySet"): "Set<Map.Entry<K,V>>",
|
|
394
|
+
("LinkedHashMap", "get"): "V",
|
|
395
|
+
("LinkedHashMap", "values"): "Collection<V>",
|
|
396
|
+
("LinkedHashMap", "keySet"): "Set<K>",
|
|
397
|
+
("LinkedHashMap", "entrySet"): "Set<Map.Entry<K,V>>",
|
|
398
|
+
("TreeMap", "get"): "V",
|
|
399
|
+
("TreeMap", "values"): "Collection<V>",
|
|
400
|
+
("TreeMap", "keySet"): "Set<K>",
|
|
401
|
+
("TreeMap", "entrySet"): "Set<Map.Entry<K,V>>",
|
|
402
|
+
("Stream", "filter"): "Stream<T>",
|
|
403
|
+
("Stream", "peek"): "Stream<T>",
|
|
404
|
+
("Stream", "distinct"): "Stream<T>",
|
|
405
|
+
("Stream", "sorted"): "Stream<T>",
|
|
406
|
+
("Stream", "toList"): "List<T>",
|
|
407
|
+
("Stream", "findFirst"): "Optional<T>",
|
|
408
|
+
("Optional", "filter"): "Optional<T>",
|
|
409
|
+
# Primitive stream specializations (`IntStream`/`LongStream`/
|
|
410
|
+
# `DoubleStream`) are not generic (JLS: no type parameter to
|
|
411
|
+
# substitute), so each fixed contract return is written as a plain,
|
|
412
|
+
# non-generic string here, the same way the `Collection.contains() ->
|
|
413
|
+
# boolean` facts above are. `map`/`filter`/`sorted`/`distinct` return
|
|
414
|
+
# the same specialized stream type (not a boxed `Stream<T>`); the
|
|
415
|
+
# reduction terminal ops (`sum`/`count`/`average`/`max`/`min`) have one
|
|
416
|
+
# fixed primitive/`OptionalX` result regardless of the pipeline's own
|
|
417
|
+
# element-producing lambda, so a *known* argument this narrows can
|
|
418
|
+
# never be defeated by an unrelated unresolvable sibling (P5 finding
|
|
419
|
+
# #1's `IntStream.range(...).map(...).sum()` shape).
|
|
420
|
+
("IntStream", "map"): "IntStream",
|
|
421
|
+
("IntStream", "filter"): "IntStream",
|
|
422
|
+
("IntStream", "sorted"): "IntStream",
|
|
423
|
+
("IntStream", "distinct"): "IntStream",
|
|
424
|
+
("IntStream", "boxed"): "Stream<Integer>",
|
|
425
|
+
("IntStream", "toArray"): "int[]",
|
|
426
|
+
("IntStream", "sum"): "int",
|
|
427
|
+
("IntStream", "count"): "long",
|
|
428
|
+
("IntStream", "average"): "OptionalDouble",
|
|
429
|
+
("IntStream", "max"): "OptionalInt",
|
|
430
|
+
("IntStream", "min"): "OptionalInt",
|
|
431
|
+
("LongStream", "map"): "LongStream",
|
|
432
|
+
("LongStream", "filter"): "LongStream",
|
|
433
|
+
("LongStream", "sorted"): "LongStream",
|
|
434
|
+
("LongStream", "distinct"): "LongStream",
|
|
435
|
+
("LongStream", "boxed"): "Stream<Long>",
|
|
436
|
+
("LongStream", "toArray"): "long[]",
|
|
437
|
+
("LongStream", "sum"): "long",
|
|
438
|
+
("LongStream", "count"): "long",
|
|
439
|
+
("LongStream", "average"): "OptionalDouble",
|
|
440
|
+
("LongStream", "max"): "OptionalLong",
|
|
441
|
+
("LongStream", "min"): "OptionalLong",
|
|
442
|
+
("DoubleStream", "map"): "DoubleStream",
|
|
443
|
+
("DoubleStream", "filter"): "DoubleStream",
|
|
444
|
+
("DoubleStream", "sorted"): "DoubleStream",
|
|
445
|
+
("DoubleStream", "distinct"): "DoubleStream",
|
|
446
|
+
("DoubleStream", "boxed"): "Stream<Double>",
|
|
447
|
+
("DoubleStream", "toArray"): "double[]",
|
|
448
|
+
("DoubleStream", "sum"): "double",
|
|
449
|
+
("DoubleStream", "count"): "long",
|
|
450
|
+
("DoubleStream", "average"): "OptionalDouble",
|
|
451
|
+
("DoubleStream", "max"): "OptionalDouble",
|
|
452
|
+
("DoubleStream", "min"): "OptionalDouble",
|
|
453
|
+
# `Stream<T>.mapToInt/mapToLong/mapToDouble` bridge to the matching
|
|
454
|
+
# primitive stream; the bridging lambda's own element type does not
|
|
455
|
+
# change this fixed contract return.
|
|
456
|
+
("Stream", "mapToInt"): "IntStream",
|
|
457
|
+
("Stream", "mapToLong"): "LongStream",
|
|
458
|
+
("Stream", "mapToDouble"): "DoubleStream",
|
|
459
|
+
# Function/Supplier results are needed when a fluent call is assigned to
|
|
460
|
+
# `var` and used as the receiver of a later source call.
|
|
461
|
+
("Function", "apply"): "R",
|
|
462
|
+
("Supplier", "get"): "T",
|
|
463
|
+
# Invoking the single abstract method of a typed JDK functional value
|
|
464
|
+
# yields its declared result variable (`BiFunction<A,B,R>.apply -> R`).
|
|
465
|
+
("BiFunction", "apply"): "R",
|
|
466
|
+
("UnaryOperator", "apply"): "T",
|
|
467
|
+
("BinaryOperator", "apply"): "T",
|
|
468
|
+
("Callable", "call"): "V",
|
|
469
|
+
# Exact `java.lang.reflect` facts, spelled fully qualified so the
|
|
470
|
+
# element type is import-independent at the call site. They are
|
|
471
|
+
# consulted only for a receiver whose declared type is not a source
|
|
472
|
+
# class, so a project type named `Method` or `Class` is never stubbed.
|
|
473
|
+
("Class", "getDeclaredMethods"): "java.lang.reflect.Method[]",
|
|
474
|
+
("Class", "getMethods"): "java.lang.reflect.Method[]",
|
|
475
|
+
("Class", "getDeclaredFields"): "java.lang.reflect.Field[]",
|
|
476
|
+
("Class", "getFields"): "java.lang.reflect.Field[]",
|
|
477
|
+
("Executable", "getParameters"): "java.lang.reflect.Parameter[]",
|
|
478
|
+
("Method", "getParameters"): "java.lang.reflect.Parameter[]",
|
|
479
|
+
("Constructor", "getParameters"): "java.lang.reflect.Parameter[]",
|
|
480
|
+
("Executable", "getGenericParameterTypes"): "java.lang.reflect.Type[]",
|
|
481
|
+
("Method", "getGenericParameterTypes"): "java.lang.reflect.Type[]",
|
|
482
|
+
("Constructor", "getGenericParameterTypes"): "java.lang.reflect.Type[]",
|
|
483
|
+
# Fixed (non-generic) `Collection`/`Map` contract returns, needed for
|
|
484
|
+
# overload-argument narrowing (P5 finding #1): `list.contains(x)`'s
|
|
485
|
+
# result is always primitive `boolean`, never a candidate's guessed
|
|
486
|
+
# reference type, regardless of the element type `E`/`K`/`V`.
|
|
487
|
+
("Collection", "contains"): "boolean",
|
|
488
|
+
("Collection", "isEmpty"): "boolean",
|
|
489
|
+
("List", "contains"): "boolean",
|
|
490
|
+
("List", "isEmpty"): "boolean",
|
|
491
|
+
("ArrayList", "contains"): "boolean",
|
|
492
|
+
("ArrayList", "isEmpty"): "boolean",
|
|
493
|
+
("LinkedList", "contains"): "boolean",
|
|
494
|
+
("LinkedList", "isEmpty"): "boolean",
|
|
495
|
+
("Set", "contains"): "boolean",
|
|
496
|
+
("Set", "isEmpty"): "boolean",
|
|
497
|
+
("SortedSet", "contains"): "boolean",
|
|
498
|
+
("SortedSet", "isEmpty"): "boolean",
|
|
499
|
+
("Map", "containsKey"): "boolean",
|
|
500
|
+
("Map", "containsValue"): "boolean",
|
|
501
|
+
("Map", "isEmpty"): "boolean",
|
|
502
|
+
("HashMap", "containsKey"): "boolean",
|
|
503
|
+
("HashMap", "containsValue"): "boolean",
|
|
504
|
+
("HashMap", "isEmpty"): "boolean",
|
|
505
|
+
("LinkedHashMap", "containsKey"): "boolean",
|
|
506
|
+
("LinkedHashMap", "containsValue"): "boolean",
|
|
507
|
+
("LinkedHashMap", "isEmpty"): "boolean",
|
|
508
|
+
("TreeMap", "containsKey"): "boolean",
|
|
509
|
+
("TreeMap", "containsValue"): "boolean",
|
|
510
|
+
("TreeMap", "isEmpty"): "boolean",
|
|
511
|
+
# Batch 24 — more fixed, non-generic JDK contract returns, all
|
|
512
|
+
# identical across every overload of the member. Same narrowing use as
|
|
513
|
+
# `contains`/`isEmpty` above; the largest remaining `overload@0.55`
|
|
514
|
+
# shapes in JUnit5 were `assertEquals(2, list.size())` (56 sites) and
|
|
515
|
+
# atomic/boxed accessors (`counter.get()`, `value.intValue()`).
|
|
516
|
+
("Collection", "size"): "int",
|
|
517
|
+
("List", "size"): "int",
|
|
518
|
+
("ArrayList", "size"): "int",
|
|
519
|
+
("LinkedList", "size"): "int",
|
|
520
|
+
("Set", "size"): "int",
|
|
521
|
+
("SortedSet", "size"): "int",
|
|
522
|
+
("Map", "size"): "int",
|
|
523
|
+
("HashMap", "size"): "int",
|
|
524
|
+
("LinkedHashMap", "size"): "int",
|
|
525
|
+
("TreeMap", "size"): "int",
|
|
526
|
+
("Stream", "count"): "long",
|
|
527
|
+
("Optional", "isPresent"): "boolean",
|
|
528
|
+
("Optional", "isEmpty"): "boolean",
|
|
529
|
+
("AtomicInteger", "get"): "int",
|
|
530
|
+
("AtomicInteger", "intValue"): "int",
|
|
531
|
+
("AtomicInteger", "incrementAndGet"): "int",
|
|
532
|
+
("AtomicInteger", "getAndIncrement"): "int",
|
|
533
|
+
("AtomicInteger", "decrementAndGet"): "int",
|
|
534
|
+
("AtomicInteger", "getAndDecrement"): "int",
|
|
535
|
+
("AtomicInteger", "addAndGet"): "int",
|
|
536
|
+
("AtomicInteger", "getAndAdd"): "int",
|
|
537
|
+
("AtomicInteger", "getAndSet"): "int",
|
|
538
|
+
("AtomicInteger", "updateAndGet"): "int",
|
|
539
|
+
("AtomicInteger", "compareAndSet"): "boolean",
|
|
540
|
+
("AtomicLong", "get"): "long",
|
|
541
|
+
("AtomicLong", "longValue"): "long",
|
|
542
|
+
("AtomicLong", "incrementAndGet"): "long",
|
|
543
|
+
("AtomicLong", "getAndIncrement"): "long",
|
|
544
|
+
("AtomicLong", "decrementAndGet"): "long",
|
|
545
|
+
("AtomicLong", "getAndDecrement"): "long",
|
|
546
|
+
("AtomicLong", "addAndGet"): "long",
|
|
547
|
+
("AtomicLong", "getAndAdd"): "long",
|
|
548
|
+
("AtomicLong", "getAndSet"): "long",
|
|
549
|
+
("AtomicLong", "updateAndGet"): "long",
|
|
550
|
+
("AtomicLong", "compareAndSet"): "boolean",
|
|
551
|
+
("AtomicBoolean", "get"): "boolean",
|
|
552
|
+
("AtomicBoolean", "getAndSet"): "boolean",
|
|
553
|
+
("AtomicBoolean", "compareAndSet"): "boolean",
|
|
554
|
+
("AtomicReference", "get"): "V",
|
|
555
|
+
("AtomicReference", "compareAndSet"): "boolean",
|
|
556
|
+
("Number", "intValue"): "int",
|
|
557
|
+
("Number", "longValue"): "long",
|
|
558
|
+
("Number", "doubleValue"): "double",
|
|
559
|
+
("Number", "floatValue"): "float",
|
|
560
|
+
("Number", "shortValue"): "short",
|
|
561
|
+
("Number", "byteValue"): "byte",
|
|
562
|
+
("Integer", "intValue"): "int",
|
|
563
|
+
("Integer", "longValue"): "long",
|
|
564
|
+
("Integer", "doubleValue"): "double",
|
|
565
|
+
("Long", "intValue"): "int",
|
|
566
|
+
("Long", "longValue"): "long",
|
|
567
|
+
("Long", "doubleValue"): "double",
|
|
568
|
+
("Short", "intValue"): "int",
|
|
569
|
+
("Short", "shortValue"): "short",
|
|
570
|
+
("Byte", "intValue"): "int",
|
|
571
|
+
("Byte", "byteValue"): "byte",
|
|
572
|
+
("Double", "intValue"): "int",
|
|
573
|
+
("Double", "longValue"): "long",
|
|
574
|
+
("Double", "doubleValue"): "double",
|
|
575
|
+
("Float", "intValue"): "int",
|
|
576
|
+
("Float", "floatValue"): "float",
|
|
577
|
+
("Float", "doubleValue"): "double",
|
|
578
|
+
("Boolean", "booleanValue"): "boolean",
|
|
579
|
+
("Character", "charValue"): "char",
|
|
580
|
+
("BooleanSupplier", "getAsBoolean"): "boolean",
|
|
581
|
+
("IntSupplier", "getAsInt"): "int",
|
|
582
|
+
("LongSupplier", "getAsLong"): "long",
|
|
583
|
+
("DoubleSupplier", "getAsDouble"): "double",
|
|
584
|
+
("Duration", "isNegative"): "boolean",
|
|
585
|
+
("Duration", "isZero"): "boolean",
|
|
586
|
+
("Duration", "toMillis"): "long",
|
|
587
|
+
("Duration", "toNanos"): "long",
|
|
588
|
+
("Duration", "toSeconds"): "long",
|
|
589
|
+
("Duration", "getSeconds"): "long",
|
|
590
|
+
# Batch 25 — fixed-return JDK members behind the remaining
|
|
591
|
+
# `assertTrue/assertFalse/assumeTrue(boolean)` vs `(BooleanSupplier)`
|
|
592
|
+
# fan-outs in JUnit5 (`filter.toPredicate().test(x)`, `stack.isEmpty()`,
|
|
593
|
+
# `lock.tryLock()`, `tempDir.exists()`, `stream.anyMatch(..)`,
|
|
594
|
+
# `Foo.class.getMethod(..).isBridge()`, `executor.awaitTermination(..)`)
|
|
595
|
+
# plus the fixed `String`/`Class`/reflection returns those chains pass
|
|
596
|
+
# through. Every entry is identical across all overloads of the member
|
|
597
|
+
# and holds for every element/type argument, exactly like the
|
|
598
|
+
# `contains`/`isEmpty` facts above; a source class sharing a JDK simple
|
|
599
|
+
# name is still never stubbed (`_generic_method_invocation_return_type`
|
|
600
|
+
# checks source resolution first).
|
|
601
|
+
("Predicate", "test"): "boolean",
|
|
602
|
+
("BiPredicate", "test"): "boolean",
|
|
603
|
+
("Stream", "anyMatch"): "boolean",
|
|
604
|
+
("Stream", "allMatch"): "boolean",
|
|
605
|
+
("Stream", "noneMatch"): "boolean",
|
|
606
|
+
("IntStream", "anyMatch"): "boolean",
|
|
607
|
+
("IntStream", "allMatch"): "boolean",
|
|
608
|
+
("IntStream", "noneMatch"): "boolean",
|
|
609
|
+
("Iterator", "hasNext"): "boolean",
|
|
610
|
+
("ListIterator", "hasNext"): "boolean",
|
|
611
|
+
("ListIterator", "hasPrevious"): "boolean",
|
|
612
|
+
("Collection", "add"): "boolean",
|
|
613
|
+
("List", "add"): "boolean",
|
|
614
|
+
("ArrayList", "add"): "boolean",
|
|
615
|
+
("LinkedList", "add"): "boolean",
|
|
616
|
+
("Set", "add"): "boolean",
|
|
617
|
+
("SortedSet", "add"): "boolean",
|
|
618
|
+
("Collection", "containsAll"): "boolean",
|
|
619
|
+
("List", "containsAll"): "boolean",
|
|
620
|
+
("Set", "containsAll"): "boolean",
|
|
621
|
+
("HashSet", "contains"): "boolean",
|
|
622
|
+
("HashSet", "isEmpty"): "boolean",
|
|
623
|
+
("HashSet", "add"): "boolean",
|
|
624
|
+
("HashSet", "size"): "int",
|
|
625
|
+
("LinkedHashSet", "contains"): "boolean",
|
|
626
|
+
("LinkedHashSet", "isEmpty"): "boolean",
|
|
627
|
+
("LinkedHashSet", "add"): "boolean",
|
|
628
|
+
("LinkedHashSet", "size"): "int",
|
|
629
|
+
("TreeSet", "contains"): "boolean",
|
|
630
|
+
("TreeSet", "isEmpty"): "boolean",
|
|
631
|
+
("TreeSet", "add"): "boolean",
|
|
632
|
+
("TreeSet", "size"): "int",
|
|
633
|
+
("EnumSet", "contains"): "boolean",
|
|
634
|
+
("EnumSet", "isEmpty"): "boolean",
|
|
635
|
+
("EnumSet", "containsAll"): "boolean",
|
|
636
|
+
("EnumSet", "size"): "int",
|
|
637
|
+
("Stack", "isEmpty"): "boolean",
|
|
638
|
+
("Stack", "empty"): "boolean",
|
|
639
|
+
("Stack", "contains"): "boolean",
|
|
640
|
+
("Stack", "add"): "boolean",
|
|
641
|
+
("Stack", "size"): "int",
|
|
642
|
+
("Stack", "search"): "int",
|
|
643
|
+
("Stack", "peek"): "E",
|
|
644
|
+
("Stack", "pop"): "E",
|
|
645
|
+
("Stack", "push"): "E",
|
|
646
|
+
("Deque", "isEmpty"): "boolean",
|
|
647
|
+
("Deque", "contains"): "boolean",
|
|
648
|
+
("Deque", "size"): "int",
|
|
649
|
+
("ArrayDeque", "isEmpty"): "boolean",
|
|
650
|
+
("ArrayDeque", "contains"): "boolean",
|
|
651
|
+
("ArrayDeque", "size"): "int",
|
|
652
|
+
("Queue", "isEmpty"): "boolean",
|
|
653
|
+
("Queue", "contains"): "boolean",
|
|
654
|
+
("Queue", "size"): "int",
|
|
655
|
+
("Map", "isEmpty"): "boolean",
|
|
656
|
+
("ConcurrentHashMap", "containsKey"): "boolean",
|
|
657
|
+
("ConcurrentHashMap", "isEmpty"): "boolean",
|
|
658
|
+
("ConcurrentHashMap", "size"): "int",
|
|
659
|
+
("ConcurrentMap", "containsKey"): "boolean",
|
|
660
|
+
("ConcurrentMap", "isEmpty"): "boolean",
|
|
661
|
+
("ConcurrentMap", "size"): "int",
|
|
662
|
+
("Lock", "tryLock"): "boolean",
|
|
663
|
+
("ReentrantLock", "tryLock"): "boolean",
|
|
664
|
+
("ReentrantLock", "isLocked"): "boolean",
|
|
665
|
+
("ReentrantLock", "isHeldByCurrentThread"): "boolean",
|
|
666
|
+
("ReentrantLock", "hasQueuedThreads"): "boolean",
|
|
667
|
+
("ReentrantLock", "isFair"): "boolean",
|
|
668
|
+
("ReentrantLock", "getHoldCount"): "int",
|
|
669
|
+
("ThreadLocal", "get"): "T",
|
|
670
|
+
("Future", "get"): "V",
|
|
671
|
+
("Future", "isDone"): "boolean",
|
|
672
|
+
("Future", "isCancelled"): "boolean",
|
|
673
|
+
("Future", "cancel"): "boolean",
|
|
674
|
+
("CompletableFuture", "get"): "T",
|
|
675
|
+
("CompletableFuture", "join"): "T",
|
|
676
|
+
("CompletableFuture", "getNow"): "T",
|
|
677
|
+
("CompletableFuture", "isDone"): "boolean",
|
|
678
|
+
("CompletableFuture", "isCancelled"): "boolean",
|
|
679
|
+
("CompletableFuture", "isCompletedExceptionally"): "boolean",
|
|
680
|
+
("CompletableFuture", "cancel"): "boolean",
|
|
681
|
+
("CompletableFuture", "complete"): "boolean",
|
|
682
|
+
("ExecutorService", "awaitTermination"): "boolean",
|
|
683
|
+
("ExecutorService", "isShutdown"): "boolean",
|
|
684
|
+
("ExecutorService", "isTerminated"): "boolean",
|
|
685
|
+
("ScheduledExecutorService", "awaitTermination"): "boolean",
|
|
686
|
+
("ScheduledExecutorService", "isShutdown"): "boolean",
|
|
687
|
+
("ScheduledExecutorService", "isTerminated"): "boolean",
|
|
688
|
+
("ThreadPoolExecutor", "awaitTermination"): "boolean",
|
|
689
|
+
("ThreadPoolExecutor", "isShutdown"): "boolean",
|
|
690
|
+
("ThreadPoolExecutor", "isTerminated"): "boolean",
|
|
691
|
+
("ForkJoinPool", "awaitTermination"): "boolean",
|
|
692
|
+
("ForkJoinPool", "awaitQuiescence"): "boolean",
|
|
693
|
+
("ForkJoinPool", "isShutdown"): "boolean",
|
|
694
|
+
("ForkJoinPool", "isTerminated"): "boolean",
|
|
695
|
+
("ForkJoinPool", "isQuiescent"): "boolean",
|
|
696
|
+
("ForkJoinPool", "getParallelism"): "int",
|
|
697
|
+
("CountDownLatch", "await"): "boolean",
|
|
698
|
+
("CountDownLatch", "getCount"): "long",
|
|
699
|
+
("Semaphore", "tryAcquire"): "boolean",
|
|
700
|
+
("Semaphore", "availablePermits"): "int",
|
|
701
|
+
("Thread", "isInterrupted"): "boolean",
|
|
702
|
+
("Thread", "isAlive"): "boolean",
|
|
703
|
+
("Thread", "isDaemon"): "boolean",
|
|
704
|
+
("Thread", "isVirtual"): "boolean",
|
|
705
|
+
("Thread", "getName"): "String",
|
|
706
|
+
("Thread", "getPriority"): "int",
|
|
707
|
+
("Thread", "getId"): "long",
|
|
708
|
+
("Thread", "threadId"): "long",
|
|
709
|
+
("File", "exists"): "boolean",
|
|
710
|
+
("File", "isDirectory"): "boolean",
|
|
711
|
+
("File", "isFile"): "boolean",
|
|
712
|
+
("File", "isAbsolute"): "boolean",
|
|
713
|
+
("File", "isHidden"): "boolean",
|
|
714
|
+
("File", "canRead"): "boolean",
|
|
715
|
+
("File", "canWrite"): "boolean",
|
|
716
|
+
("File", "canExecute"): "boolean",
|
|
717
|
+
("File", "createNewFile"): "boolean",
|
|
718
|
+
("File", "delete"): "boolean",
|
|
719
|
+
("File", "mkdir"): "boolean",
|
|
720
|
+
("File", "mkdirs"): "boolean",
|
|
721
|
+
("File", "renameTo"): "boolean",
|
|
722
|
+
("File", "setReadOnly"): "boolean",
|
|
723
|
+
("File", "setReadable"): "boolean",
|
|
724
|
+
("File", "setWritable"): "boolean",
|
|
725
|
+
("File", "setExecutable"): "boolean",
|
|
726
|
+
("File", "setLastModified"): "boolean",
|
|
727
|
+
("File", "getName"): "String",
|
|
728
|
+
("File", "getPath"): "String",
|
|
729
|
+
("File", "getParent"): "String",
|
|
730
|
+
("File", "getAbsolutePath"): "String",
|
|
731
|
+
("File", "getCanonicalPath"): "String",
|
|
732
|
+
("File", "getParentFile"): "java.io.File",
|
|
733
|
+
("File", "getAbsoluteFile"): "java.io.File",
|
|
734
|
+
("File", "getCanonicalFile"): "java.io.File",
|
|
735
|
+
("File", "toPath"): "java.nio.file.Path",
|
|
736
|
+
("File", "length"): "long",
|
|
737
|
+
("File", "lastModified"): "long",
|
|
738
|
+
("File", "listFiles"): "java.io.File[]",
|
|
739
|
+
("File", "list"): "String[]",
|
|
740
|
+
("Path", "toFile"): "java.io.File",
|
|
741
|
+
("Path", "getFileName"): "java.nio.file.Path",
|
|
742
|
+
("Path", "getParent"): "java.nio.file.Path",
|
|
743
|
+
("Path", "getRoot"): "java.nio.file.Path",
|
|
744
|
+
("Path", "toAbsolutePath"): "java.nio.file.Path",
|
|
745
|
+
("Path", "normalize"): "java.nio.file.Path",
|
|
746
|
+
("Path", "resolve"): "java.nio.file.Path",
|
|
747
|
+
("Path", "resolveSibling"): "java.nio.file.Path",
|
|
748
|
+
("Path", "relativize"): "java.nio.file.Path",
|
|
749
|
+
("Path", "toRealPath"): "java.nio.file.Path",
|
|
750
|
+
("Path", "startsWith"): "boolean",
|
|
751
|
+
("Path", "endsWith"): "boolean",
|
|
752
|
+
("Path", "isAbsolute"): "boolean",
|
|
753
|
+
("Path", "getNameCount"): "int",
|
|
754
|
+
("Class", "isArray"): "boolean",
|
|
755
|
+
("Class", "isPrimitive"): "boolean",
|
|
756
|
+
("Class", "isInterface"): "boolean",
|
|
757
|
+
("Class", "isEnum"): "boolean",
|
|
758
|
+
("Class", "isRecord"): "boolean",
|
|
759
|
+
("Class", "isAnnotation"): "boolean",
|
|
760
|
+
("Class", "isAssignableFrom"): "boolean",
|
|
761
|
+
("Class", "isInstance"): "boolean",
|
|
762
|
+
("Class", "isAnonymousClass"): "boolean",
|
|
763
|
+
("Class", "isMemberClass"): "boolean",
|
|
764
|
+
("Class", "isLocalClass"): "boolean",
|
|
765
|
+
("Class", "isSynthetic"): "boolean",
|
|
766
|
+
("Class", "isSealed"): "boolean",
|
|
767
|
+
("Class", "isHidden"): "boolean",
|
|
768
|
+
("Class", "isNestmateOf"): "boolean",
|
|
769
|
+
("Class", "isAnnotationPresent"): "boolean",
|
|
770
|
+
("Class", "desiredAssertionStatus"): "boolean",
|
|
771
|
+
("Class", "getComponentType"): "Class",
|
|
772
|
+
("Class", "getSuperclass"): "Class",
|
|
773
|
+
("Class", "getEnclosingClass"): "Class",
|
|
774
|
+
("Class", "getDeclaringClass"): "Class",
|
|
775
|
+
("Class", "getNestHost"): "Class",
|
|
776
|
+
("Class", "getInterfaces"): "Class[]",
|
|
777
|
+
("Class", "getMethod"): "java.lang.reflect.Method",
|
|
778
|
+
("Class", "getConstructor"): "java.lang.reflect.Constructor",
|
|
779
|
+
("Class", "getDeclaredConstructor"): "java.lang.reflect.Constructor",
|
|
780
|
+
("Class", "getField"): "java.lang.reflect.Field",
|
|
781
|
+
("Class", "getDeclaredField"): "java.lang.reflect.Field",
|
|
782
|
+
("Class", "getModifiers"): "int",
|
|
783
|
+
("Class", "getCanonicalName"): "String",
|
|
784
|
+
("Class", "getTypeName"): "String",
|
|
785
|
+
("Class", "getPackageName"): "String",
|
|
786
|
+
("Class", "getModule"): "java.lang.Module",
|
|
787
|
+
("Module", "isNamed"): "boolean",
|
|
788
|
+
("Module", "getName"): "String",
|
|
789
|
+
("Method", "isBridge"): "boolean",
|
|
790
|
+
("Method", "isSynthetic"): "boolean",
|
|
791
|
+
("Method", "isDefault"): "boolean",
|
|
792
|
+
("Method", "isVarArgs"): "boolean",
|
|
793
|
+
("Method", "isAnnotationPresent"): "boolean",
|
|
794
|
+
("Method", "getModifiers"): "int",
|
|
795
|
+
("Method", "getParameterCount"): "int",
|
|
796
|
+
("Method", "getReturnType"): "Class",
|
|
797
|
+
("Method", "getDeclaringClass"): "Class",
|
|
798
|
+
("Constructor", "isSynthetic"): "boolean",
|
|
799
|
+
("Constructor", "isVarArgs"): "boolean",
|
|
800
|
+
("Constructor", "getModifiers"): "int",
|
|
801
|
+
("Constructor", "getParameterCount"): "int",
|
|
802
|
+
("Constructor", "getDeclaringClass"): "Class",
|
|
803
|
+
("Field", "getName"): "String",
|
|
804
|
+
("Field", "getType"): "Class",
|
|
805
|
+
("Field", "getDeclaringClass"): "Class",
|
|
806
|
+
("Field", "getModifiers"): "int",
|
|
807
|
+
("Field", "isSynthetic"): "boolean",
|
|
808
|
+
("Field", "isEnumConstant"): "boolean",
|
|
809
|
+
("Parameter", "getName"): "String",
|
|
810
|
+
("Parameter", "getType"): "Class",
|
|
811
|
+
("Parameter", "isNamePresent"): "boolean",
|
|
812
|
+
("Parameter", "isVarArgs"): "boolean",
|
|
813
|
+
("Pattern", "matcher"): "java.util.regex.Matcher",
|
|
814
|
+
("Pattern", "pattern"): "String",
|
|
815
|
+
("Matcher", "matches"): "boolean",
|
|
816
|
+
("Matcher", "find"): "boolean",
|
|
817
|
+
("Matcher", "lookingAt"): "boolean",
|
|
818
|
+
("Matcher", "hitEnd"): "boolean",
|
|
819
|
+
("Matcher", "group"): "String",
|
|
820
|
+
("Matcher", "groupCount"): "int",
|
|
821
|
+
("Matcher", "start"): "int",
|
|
822
|
+
("Matcher", "end"): "int",
|
|
823
|
+
("Throwable", "getMessage"): "String",
|
|
824
|
+
("Throwable", "getLocalizedMessage"): "String",
|
|
825
|
+
("Throwable", "getCause"): "Throwable",
|
|
826
|
+
("Throwable", "getStackTrace"): "StackTraceElement[]",
|
|
827
|
+
("Throwable", "getSuppressed"): "Throwable[]",
|
|
828
|
+
("Exception", "getMessage"): "String",
|
|
829
|
+
("Exception", "getLocalizedMessage"): "String",
|
|
830
|
+
("Exception", "getCause"): "Throwable",
|
|
831
|
+
("Exception", "getStackTrace"): "StackTraceElement[]",
|
|
832
|
+
("RuntimeException", "getMessage"): "String",
|
|
833
|
+
("RuntimeException", "getCause"): "Throwable",
|
|
834
|
+
("RuntimeException", "getStackTrace"): "StackTraceElement[]",
|
|
835
|
+
("Error", "getMessage"): "String",
|
|
836
|
+
("Error", "getCause"): "Throwable",
|
|
837
|
+
("Error", "getStackTrace"): "StackTraceElement[]",
|
|
838
|
+
("AssertionError", "getMessage"): "String",
|
|
839
|
+
("AssertionError", "getCause"): "Throwable",
|
|
840
|
+
("AssertionError", "getStackTrace"): "StackTraceElement[]",
|
|
841
|
+
("IllegalArgumentException", "getMessage"): "String",
|
|
842
|
+
("IllegalArgumentException", "getCause"): "Throwable",
|
|
843
|
+
("IllegalStateException", "getMessage"): "String",
|
|
844
|
+
("IllegalStateException", "getCause"): "Throwable",
|
|
845
|
+
("UnsupportedOperationException", "getMessage"): "String",
|
|
846
|
+
("NullPointerException", "getMessage"): "String",
|
|
847
|
+
("IOException", "getMessage"): "String",
|
|
848
|
+
("IOException", "getCause"): "Throwable",
|
|
849
|
+
("UncheckedIOException", "getMessage"): "String",
|
|
850
|
+
("UncheckedIOException", "getCause"): "IOException",
|
|
851
|
+
("InterruptedException", "getMessage"): "String",
|
|
852
|
+
("ExecutionException", "getMessage"): "String",
|
|
853
|
+
("ExecutionException", "getCause"): "Throwable",
|
|
854
|
+
("TimeoutException", "getMessage"): "String",
|
|
855
|
+
("ReflectiveOperationException", "getMessage"): "String",
|
|
856
|
+
("ClassNotFoundException", "getMessage"): "String",
|
|
857
|
+
("NoSuchMethodException", "getMessage"): "String",
|
|
858
|
+
("InvocationTargetException", "getMessage"): "String",
|
|
859
|
+
("InvocationTargetException", "getCause"): "Throwable",
|
|
860
|
+
("InvocationTargetException", "getTargetException"): "Throwable",
|
|
861
|
+
("StackTraceElement", "getClassName"): "String",
|
|
862
|
+
("StackTraceElement", "getMethodName"): "String",
|
|
863
|
+
("StackTraceElement", "getFileName"): "String",
|
|
864
|
+
("StackTraceElement", "getLineNumber"): "int",
|
|
865
|
+
("StackTraceElement", "isNativeMethod"): "boolean",
|
|
866
|
+
# Batch 26 — `java.time` accessors (fixed `int`/`long`/`boolean`
|
|
867
|
+
# results on every temporal type that declares them), `Comparable`,
|
|
868
|
+
# primitive-stream pipeline steps with a fixed result stream, and the
|
|
869
|
+
# `InputStream`/`Reader`/`ClassLoader` members behind remaining
|
|
870
|
+
# `assertEquals` fan-outs.
|
|
871
|
+
("LocalDate", "getYear"): "int",
|
|
872
|
+
("LocalDate", "getMonthValue"): "int",
|
|
873
|
+
("LocalDate", "getDayOfMonth"): "int",
|
|
874
|
+
("LocalDate", "getDayOfYear"): "int",
|
|
875
|
+
("LocalDate", "lengthOfMonth"): "int",
|
|
876
|
+
("LocalDate", "lengthOfYear"): "int",
|
|
877
|
+
("LocalDate", "toEpochDay"): "long",
|
|
878
|
+
("LocalDate", "isLeapYear"): "boolean",
|
|
879
|
+
("LocalDate", "isBefore"): "boolean",
|
|
880
|
+
("LocalDate", "isAfter"): "boolean",
|
|
881
|
+
("LocalDate", "isEqual"): "boolean",
|
|
882
|
+
("LocalDateTime", "getYear"): "int",
|
|
883
|
+
("LocalDateTime", "getMonthValue"): "int",
|
|
884
|
+
("LocalDateTime", "getDayOfMonth"): "int",
|
|
885
|
+
("LocalDateTime", "getDayOfYear"): "int",
|
|
886
|
+
("LocalDateTime", "getHour"): "int",
|
|
887
|
+
("LocalDateTime", "getMinute"): "int",
|
|
888
|
+
("LocalDateTime", "getSecond"): "int",
|
|
889
|
+
("LocalDateTime", "getNano"): "int",
|
|
890
|
+
("LocalDateTime", "isBefore"): "boolean",
|
|
891
|
+
("LocalDateTime", "isAfter"): "boolean",
|
|
892
|
+
("LocalDateTime", "isEqual"): "boolean",
|
|
893
|
+
("LocalTime", "getHour"): "int",
|
|
894
|
+
("LocalTime", "getMinute"): "int",
|
|
895
|
+
("LocalTime", "getSecond"): "int",
|
|
896
|
+
("LocalTime", "getNano"): "int",
|
|
897
|
+
("LocalTime", "toSecondOfDay"): "int",
|
|
898
|
+
("LocalTime", "toNanoOfDay"): "long",
|
|
899
|
+
("LocalTime", "isBefore"): "boolean",
|
|
900
|
+
("LocalTime", "isAfter"): "boolean",
|
|
901
|
+
("ZonedDateTime", "getYear"): "int",
|
|
902
|
+
("ZonedDateTime", "getMonthValue"): "int",
|
|
903
|
+
("ZonedDateTime", "getDayOfMonth"): "int",
|
|
904
|
+
("ZonedDateTime", "getHour"): "int",
|
|
905
|
+
("ZonedDateTime", "getMinute"): "int",
|
|
906
|
+
("ZonedDateTime", "getSecond"): "int",
|
|
907
|
+
("ZonedDateTime", "getNano"): "int",
|
|
908
|
+
("ZonedDateTime", "toEpochSecond"): "long",
|
|
909
|
+
("ZonedDateTime", "isBefore"): "boolean",
|
|
910
|
+
("ZonedDateTime", "isAfter"): "boolean",
|
|
911
|
+
("OffsetDateTime", "getYear"): "int",
|
|
912
|
+
("OffsetDateTime", "getMonthValue"): "int",
|
|
913
|
+
("OffsetDateTime", "getDayOfMonth"): "int",
|
|
914
|
+
("OffsetDateTime", "getHour"): "int",
|
|
915
|
+
("OffsetDateTime", "getMinute"): "int",
|
|
916
|
+
("OffsetDateTime", "getSecond"): "int",
|
|
917
|
+
("OffsetDateTime", "toEpochSecond"): "long",
|
|
918
|
+
("Instant", "getEpochSecond"): "long",
|
|
919
|
+
("Instant", "toEpochMilli"): "long",
|
|
920
|
+
("Instant", "getNano"): "int",
|
|
921
|
+
("Instant", "isBefore"): "boolean",
|
|
922
|
+
("Instant", "isAfter"): "boolean",
|
|
923
|
+
("Year", "getValue"): "int",
|
|
924
|
+
("Year", "length"): "int",
|
|
925
|
+
("Year", "isLeap"): "boolean",
|
|
926
|
+
("Year", "isBefore"): "boolean",
|
|
927
|
+
("Year", "isAfter"): "boolean",
|
|
928
|
+
("YearMonth", "getYear"): "int",
|
|
929
|
+
("YearMonth", "getMonthValue"): "int",
|
|
930
|
+
("YearMonth", "lengthOfMonth"): "int",
|
|
931
|
+
("YearMonth", "lengthOfYear"): "int",
|
|
932
|
+
("Period", "getYears"): "int",
|
|
933
|
+
("Period", "getMonths"): "int",
|
|
934
|
+
("Period", "getDays"): "int",
|
|
935
|
+
("Period", "toTotalMonths"): "long",
|
|
936
|
+
("Period", "isNegative"): "boolean",
|
|
937
|
+
("Period", "isZero"): "boolean",
|
|
938
|
+
("Duration", "toDays"): "long",
|
|
939
|
+
("Duration", "toHours"): "long",
|
|
940
|
+
("Duration", "toMinutes"): "long",
|
|
941
|
+
("Duration", "getNano"): "int",
|
|
942
|
+
("Duration", "compareTo"): "int",
|
|
943
|
+
("Comparable", "compareTo"): "int",
|
|
944
|
+
("Comparator", "compare"): "int",
|
|
945
|
+
("IntStream", "limit"): "IntStream",
|
|
946
|
+
("IntStream", "skip"): "IntStream",
|
|
947
|
+
("IntStream", "peek"): "IntStream",
|
|
948
|
+
("IntStream", "asLongStream"): "LongStream",
|
|
949
|
+
("IntStream", "asDoubleStream"): "DoubleStream",
|
|
950
|
+
("LongStream", "limit"): "LongStream",
|
|
951
|
+
("LongStream", "skip"): "LongStream",
|
|
952
|
+
("LongStream", "peek"): "LongStream",
|
|
953
|
+
("DoubleStream", "limit"): "DoubleStream",
|
|
954
|
+
("DoubleStream", "skip"): "DoubleStream",
|
|
955
|
+
("DoubleStream", "peek"): "DoubleStream",
|
|
956
|
+
("Stream", "limit"): "Stream<T>",
|
|
957
|
+
("Stream", "skip"): "Stream<T>",
|
|
958
|
+
("InputStream", "read"): "int",
|
|
959
|
+
("InputStream", "available"): "int",
|
|
960
|
+
("InputStream", "readAllBytes"): "byte[]",
|
|
961
|
+
("Reader", "read"): "int",
|
|
962
|
+
("BufferedReader", "readLine"): "String",
|
|
963
|
+
("ClassLoader", "loadClass"): "Class",
|
|
964
|
+
("ClassLoader", "getResource"): "java.net.URL",
|
|
965
|
+
("ClassLoader", "getParent"): "ClassLoader",
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
JAVA_GENERIC_TYPE_PARAM_STUBS: Dict[str, List[str]] = {
|
|
969
|
+
"Iterable": ["T"],
|
|
970
|
+
"AtomicReference": ["V"],
|
|
971
|
+
"Collection": ["E"],
|
|
972
|
+
"List": ["E"],
|
|
973
|
+
"Set": ["E"],
|
|
974
|
+
"SortedSet": ["E"],
|
|
975
|
+
"ArrayList": ["E"],
|
|
976
|
+
"LinkedList": ["E"],
|
|
977
|
+
"Iterator": ["T"],
|
|
978
|
+
"ListIterator": ["E"],
|
|
979
|
+
"Optional": ["T"],
|
|
980
|
+
"Stream": ["T"],
|
|
981
|
+
"Map": ["K", "V"],
|
|
982
|
+
"Entry": ["K", "V"],
|
|
983
|
+
"HashMap": ["K", "V"],
|
|
984
|
+
"LinkedHashMap": ["K", "V"],
|
|
985
|
+
"TreeMap": ["K", "V"],
|
|
986
|
+
"Function": ["T", "R"],
|
|
987
|
+
"Supplier": ["T"],
|
|
988
|
+
"BiFunction": ["T", "U", "R"],
|
|
989
|
+
"UnaryOperator": ["T"],
|
|
990
|
+
"BinaryOperator": ["T"],
|
|
991
|
+
"Callable": ["V"],
|
|
992
|
+
"HashSet": ["E"],
|
|
993
|
+
"LinkedHashSet": ["E"],
|
|
994
|
+
"TreeSet": ["E"],
|
|
995
|
+
"Stack": ["E"],
|
|
996
|
+
"ThreadLocal": ["T"],
|
|
997
|
+
"Future": ["V"],
|
|
998
|
+
"CompletableFuture": ["T"],
|
|
999
|
+
}
|
|
1000
|
+
# Stream operations whose first functional argument consumes one stream
|
|
1001
|
+
# element. This is used only to type an implicit lambda parameter from an
|
|
1002
|
+
# already-proven `Stream<T>` receiver; it does not fabricate a call target
|
|
1003
|
+
# for the external JDK method itself.
|
|
1004
|
+
JAVA_STREAM_ELEMENT_LAMBDA_METHODS: FrozenSet[str] = frozenset({
|
|
1005
|
+
"allMatch", "anyMatch", "filter", "forEach", "forEachOrdered", "map",
|
|
1006
|
+
"noneMatch", "peek",
|
|
1007
|
+
# Batch 26: the remaining element-consuming single-lambda steps —
|
|
1008
|
+
# `mapToObj`/`mapToInt`/`mapToLong`/`mapToDouble`/`flatMap`/
|
|
1009
|
+
# `takeWhile`/`dropWhile` all receive one element as their sole lambda
|
|
1010
|
+
# parameter (`IntStream.range(..).mapToObj(n -> ..)` is the JUnit5
|
|
1011
|
+
# dynamic-test idiom).
|
|
1012
|
+
"mapToObj", "mapToInt", "mapToLong", "mapToDouble", "flatMap",
|
|
1013
|
+
"takeWhile", "dropWhile",
|
|
1014
|
+
# `Comparator<? super T>` consumers: every lambda parameter is `T`
|
|
1015
|
+
# (`sorted((l, r) -> ...)`, `min`, `max`). `reduce` is excluded because
|
|
1016
|
+
# its identity overload places the accumulator at argument index 1.
|
|
1017
|
+
"max", "min", "sorted",
|
|
1018
|
+
})
|
|
1019
|
+
JAVA_OPTIONAL_ELEMENT_LAMBDA_METHODS: FrozenSet[str] = frozenset({
|
|
1020
|
+
"filter", "flatMap", "ifPresent", "ifPresentOrElse", "map",
|
|
1021
|
+
})
|
|
1022
|
+
# `org.assertj.core.api` static-factory owners whose `assertThat(actual)`
|
|
1023
|
+
# this resolver recognizes by argument type alone (AssertJ's own overload
|
|
1024
|
+
# set lives outside the analyzed source and cannot be resolved structurally).
|
|
1025
|
+
# Used only to type a `Consumer`/`Predicate` argument passed to the returned
|
|
1026
|
+
# assert wrapper's own fluent methods one hop later (`hasValueSatisfying`,
|
|
1027
|
+
# `satisfies`, `allSatisfy`, ...) — never to fabricate a call edge to AssertJ
|
|
1028
|
+
# itself.
|
|
1029
|
+
ASSERTJ_ASSERT_FACTORY_OWNERS: FrozenSet[str] = frozenset({
|
|
1030
|
+
"org.assertj.core.api.Assertions",
|
|
1031
|
+
"org.assertj.core.api.AssertionsForClassTypes",
|
|
1032
|
+
"org.assertj.core.api.AssertionsForInterfaceTypes",
|
|
1033
|
+
})
|
|
1034
|
+
# AssertJ assert-wrapper simple name -> its `Consumer<element>`-typed fluent
|
|
1035
|
+
# methods, keyed by the wrapper this resolver derives in
|
|
1036
|
+
# `_assertj_assertthat_return_type` (`ObjectAssert`, `OptionalAssert`,
|
|
1037
|
+
# `ListAssert`). Real AssertJ also exposes `IterableAssert` for a plain
|
|
1038
|
+
# `Iterable` actual; kept here too since `allSatisfy`/`anySatisfy`/
|
|
1039
|
+
# `noneSatisfy` share the identical signature on both.
|
|
1040
|
+
ASSERTJ_CONSUMER_SATISFIES_METHODS: FrozenSet[str] = frozenset({
|
|
1041
|
+
"hasValueSatisfying", "satisfies", "allSatisfy", "anySatisfy", "noneSatisfy",
|
|
1042
|
+
})
|
|
1043
|
+
# Same wrappers' `Predicate<element>`-typed fluent methods.
|
|
1044
|
+
ASSERTJ_PREDICATE_METHODS: FrozenSet[str] = frozenset({
|
|
1045
|
+
"filteredOn", "allMatch", "anyMatch", "noneMatch",
|
|
1046
|
+
})
|
|
1047
|
+
# `java.lang` simple names that are in scope without an import. A file that
|
|
1048
|
+
# spells one of these without a same-package or imported declaration means the
|
|
1049
|
+
# JDK type; it must never be recovered as an unrelated project class that
|
|
1050
|
+
# happens to share the simple name.
|
|
1051
|
+
JAVA_LANG_SIMPLE_TYPES: FrozenSet[str] = frozenset({
|
|
1052
|
+
"AssertionError", "Boolean", "Byte", "Character", "CharSequence", "Class",
|
|
1053
|
+
"ClassLoader",
|
|
1054
|
+
"CloneNotSupportedException",
|
|
1055
|
+
"Comparable", "Double", "Enum", "Error", "Exception", "Float", "Integer",
|
|
1056
|
+
"IllegalAccessException", "InterruptedException", "Iterable", "LinkageError", "Long", "Math", "NullPointerException", "Number",
|
|
1057
|
+
"Object",
|
|
1058
|
+
"Record", "Runnable",
|
|
1059
|
+
"RuntimeException", "Short", "String", "StringBuilder", "StringBuffer",
|
|
1060
|
+
"System", "Thread", "Throwable", "Void",
|
|
1061
|
+
})
|
|
1062
|
+
# Exact external static-return facts needed for overload argument inference.
|
|
1063
|
+
# Keyed by FQN so a project-local same-simple-name class never matches.
|
|
1064
|
+
JAVA_STATIC_METHOD_STUB_RETURNS: Dict[Tuple[str, str], str] = {
|
|
1065
|
+
("java.lang.String", "valueOf"): "String",
|
|
1066
|
+
# Every overload of `String.format`/`String.join` returns `String`. A
|
|
1067
|
+
# `String.format(...)` argument is the most common shape of the JUnit5
|
|
1068
|
+
# `overload/java_resolver@0.55` stratum alongside `"...".formatted(...)`
|
|
1069
|
+
# (`assertTrue(cond, String.format(...))` vs the `Supplier<String>`
|
|
1070
|
+
# sibling; `new PreconditionViolationException(String.format(...))`).
|
|
1071
|
+
("java.lang.String", "format"): "String",
|
|
1072
|
+
("java.lang.String", "join"): "String",
|
|
1073
|
+
# Batch 24: `java.lang` parsers (no import needed — see
|
|
1074
|
+
# `_external_static_call_return_type`'s `java.lang` default) and the
|
|
1075
|
+
# `java.nio.file.Files` predicates/readers; every overload of each has
|
|
1076
|
+
# the one fixed return listed. `assertTrue(Files.exists(dir))` (JUnit5
|
|
1077
|
+
# `TempDirectory*Tests`, 51 sites) fanned out to `assertTrue
|
|
1078
|
+
# (BooleanSupplier)` before.
|
|
1079
|
+
("java.lang.Integer", "parseInt"): "int",
|
|
1080
|
+
("java.lang.Long", "parseLong"): "long",
|
|
1081
|
+
("java.lang.Short", "parseShort"): "short",
|
|
1082
|
+
("java.lang.Byte", "parseByte"): "byte",
|
|
1083
|
+
("java.lang.Double", "parseDouble"): "double",
|
|
1084
|
+
("java.lang.Float", "parseFloat"): "float",
|
|
1085
|
+
("java.lang.Boolean", "parseBoolean"): "boolean",
|
|
1086
|
+
("java.nio.file.Files", "exists"): "boolean",
|
|
1087
|
+
("java.nio.file.Files", "notExists"): "boolean",
|
|
1088
|
+
("java.nio.file.Files", "isDirectory"): "boolean",
|
|
1089
|
+
("java.nio.file.Files", "isRegularFile"): "boolean",
|
|
1090
|
+
("java.nio.file.Files", "isReadable"): "boolean",
|
|
1091
|
+
("java.nio.file.Files", "isWritable"): "boolean",
|
|
1092
|
+
("java.nio.file.Files", "isExecutable"): "boolean",
|
|
1093
|
+
("java.nio.file.Files", "isHidden"): "boolean",
|
|
1094
|
+
("java.nio.file.Files", "isSymbolicLink"): "boolean",
|
|
1095
|
+
("java.nio.file.Files", "isSameFile"): "boolean",
|
|
1096
|
+
("java.nio.file.Files", "deleteIfExists"): "boolean",
|
|
1097
|
+
("java.nio.file.Files", "readAllLines"): "List<String>",
|
|
1098
|
+
("java.nio.file.Files", "readString"): "String",
|
|
1099
|
+
("java.nio.file.Files", "readAllBytes"): "byte[]",
|
|
1100
|
+
("java.nio.file.Files", "lines"): "Stream<String>",
|
|
1101
|
+
("java.nio.file.Files", "size"): "long",
|
|
1102
|
+
# Every overload of `Paths.get` has the fixed declared return `Path`.
|
|
1103
|
+
# Keep the key FQN-scoped so a source `Paths` type never receives this
|
|
1104
|
+
# external JDK contract accidentally.
|
|
1105
|
+
("java.nio.file.Paths", "get"): "Path",
|
|
1106
|
+
("java.time.Clock", "systemDefaultZone"): "Clock",
|
|
1107
|
+
# `java.time.Year`'s three fixed-return static factories — needed for
|
|
1108
|
+
# overload narrowing: `YearHasPassed.of(int)` derives a `Year` via one of
|
|
1109
|
+
# these and passes it to the sibling `YearHasPassed.of(Year)`, which used
|
|
1110
|
+
# to fan out against the `int` overload itself since each nested call's
|
|
1111
|
+
# return type was unknown (spring-modulith benchmark, one call site each
|
|
1112
|
+
# in `YearHasPassed.java` (`of`), `Moments.java` (`from`) and
|
|
1113
|
+
# `MomentsUnitTests.java` (`now`)).
|
|
1114
|
+
("java.time.Year", "of"): "Year",
|
|
1115
|
+
("java.time.Year", "from"): "Year",
|
|
1116
|
+
("java.time.Year", "now"): "Year",
|
|
1117
|
+
# `IntStream`/`LongStream`'s two static range factories are fixed to
|
|
1118
|
+
# their own (non-generic) stream type regardless of the bound
|
|
1119
|
+
# expressions, feeding the primitive-stream terminal-op facts in
|
|
1120
|
+
# `JAVA_GENERIC_METHOD_STUB_RETURNS` above.
|
|
1121
|
+
("java.util.stream.IntStream", "range"): "IntStream",
|
|
1122
|
+
("java.util.stream.IntStream", "rangeClosed"): "IntStream",
|
|
1123
|
+
("java.util.stream.LongStream", "range"): "LongStream",
|
|
1124
|
+
("java.util.stream.LongStream", "rangeClosed"): "LongStream",
|
|
1125
|
+
# Batch 25 — fixed static returns behind remaining JUnit5 boolean/int/
|
|
1126
|
+
# String overload arguments (`Thread.interrupted()`, `Modifier.isPublic
|
|
1127
|
+
# (m)`, `Objects.equals(a, b)`, `Arrays.toString(x)`, `System.
|
|
1128
|
+
# getProperty(k)`) and the fluent roots they chain from
|
|
1129
|
+
# (`Thread.currentThread().isInterrupted()`, `Pattern.compile(p).
|
|
1130
|
+
# matcher(s).matches()`, `Files.createTempDirectory(p).toFile()`).
|
|
1131
|
+
("java.lang.Thread", "interrupted"): "boolean",
|
|
1132
|
+
("java.lang.Thread", "currentThread"): "Thread",
|
|
1133
|
+
("java.lang.Thread", "activeCount"): "int",
|
|
1134
|
+
("java.lang.System", "currentTimeMillis"): "long",
|
|
1135
|
+
("java.lang.System", "nanoTime"): "long",
|
|
1136
|
+
("java.lang.System", "getProperty"): "String",
|
|
1137
|
+
("java.lang.System", "getenv"): "String",
|
|
1138
|
+
("java.lang.System", "lineSeparator"): "String",
|
|
1139
|
+
("java.lang.System", "identityHashCode"): "int",
|
|
1140
|
+
("java.lang.Boolean", "toString"): "String",
|
|
1141
|
+
("java.lang.Boolean", "logicalAnd"): "boolean",
|
|
1142
|
+
("java.lang.Boolean", "logicalOr"): "boolean",
|
|
1143
|
+
("java.lang.Boolean", "logicalXor"): "boolean",
|
|
1144
|
+
("java.lang.Boolean", "getBoolean"): "boolean",
|
|
1145
|
+
("java.lang.Character", "isDigit"): "boolean",
|
|
1146
|
+
("java.lang.Character", "isLetter"): "boolean",
|
|
1147
|
+
("java.lang.Character", "isLetterOrDigit"): "boolean",
|
|
1148
|
+
("java.lang.Character", "isWhitespace"): "boolean",
|
|
1149
|
+
("java.lang.Character", "isSpaceChar"): "boolean",
|
|
1150
|
+
("java.lang.Character", "isUpperCase"): "boolean",
|
|
1151
|
+
("java.lang.Character", "isLowerCase"): "boolean",
|
|
1152
|
+
("java.lang.Character", "isAlphabetic"): "boolean",
|
|
1153
|
+
("java.lang.Character", "isJavaIdentifierStart"): "boolean",
|
|
1154
|
+
("java.lang.Character", "isJavaIdentifierPart"): "boolean",
|
|
1155
|
+
("java.lang.Integer", "toString"): "String",
|
|
1156
|
+
("java.lang.Integer", "toHexString"): "String",
|
|
1157
|
+
("java.lang.Integer", "toBinaryString"): "String",
|
|
1158
|
+
("java.lang.Integer", "compare"): "int",
|
|
1159
|
+
("java.lang.Integer", "signum"): "int",
|
|
1160
|
+
("java.lang.Integer", "bitCount"): "int",
|
|
1161
|
+
("java.lang.Integer", "sum"): "int",
|
|
1162
|
+
("java.lang.Integer", "max"): "int",
|
|
1163
|
+
("java.lang.Integer", "min"): "int",
|
|
1164
|
+
("java.lang.Long", "toString"): "String",
|
|
1165
|
+
("java.lang.Long", "toHexString"): "String",
|
|
1166
|
+
("java.lang.Long", "compare"): "int",
|
|
1167
|
+
("java.lang.Long", "signum"): "int",
|
|
1168
|
+
("java.lang.Long", "sum"): "long",
|
|
1169
|
+
("java.lang.Long", "max"): "long",
|
|
1170
|
+
("java.lang.Long", "min"): "long",
|
|
1171
|
+
("java.lang.Double", "toString"): "String",
|
|
1172
|
+
("java.lang.Double", "compare"): "int",
|
|
1173
|
+
("java.lang.Double", "isNaN"): "boolean",
|
|
1174
|
+
("java.lang.Double", "isInfinite"): "boolean",
|
|
1175
|
+
("java.lang.Double", "isFinite"): "boolean",
|
|
1176
|
+
("java.lang.Double", "sum"): "double",
|
|
1177
|
+
("java.lang.Double", "max"): "double",
|
|
1178
|
+
("java.lang.Double", "min"): "double",
|
|
1179
|
+
("java.lang.Float", "isNaN"): "boolean",
|
|
1180
|
+
("java.lang.Float", "isInfinite"): "boolean",
|
|
1181
|
+
("java.lang.Float", "isFinite"): "boolean",
|
|
1182
|
+
("java.lang.Math", "sqrt"): "double",
|
|
1183
|
+
("java.lang.Math", "pow"): "double",
|
|
1184
|
+
("java.lang.Math", "floor"): "double",
|
|
1185
|
+
("java.lang.Math", "ceil"): "double",
|
|
1186
|
+
("java.lang.Math", "random"): "double",
|
|
1187
|
+
("java.lang.Math", "toIntExact"): "int",
|
|
1188
|
+
("java.lang.String", "copyValueOf"): "String",
|
|
1189
|
+
("java.lang.Class", "forName"): "Class",
|
|
1190
|
+
# Batch 26 — boxed `valueOf` factories (every overload returns the box),
|
|
1191
|
+
# `IntStream`/`Stream` sources whose result type is fixed, class loading.
|
|
1192
|
+
("java.lang.Integer", "valueOf"): "Integer",
|
|
1193
|
+
("java.lang.Long", "valueOf"): "Long",
|
|
1194
|
+
("java.lang.Short", "valueOf"): "Short",
|
|
1195
|
+
("java.lang.Byte", "valueOf"): "Byte",
|
|
1196
|
+
("java.lang.Double", "valueOf"): "Double",
|
|
1197
|
+
("java.lang.Float", "valueOf"): "Float",
|
|
1198
|
+
("java.lang.Boolean", "valueOf"): "Boolean",
|
|
1199
|
+
("java.lang.Character", "valueOf"): "Character",
|
|
1200
|
+
("java.util.stream.IntStream", "of"): "IntStream",
|
|
1201
|
+
("java.util.stream.IntStream", "iterate"): "IntStream",
|
|
1202
|
+
("java.util.stream.IntStream", "generate"): "IntStream",
|
|
1203
|
+
("java.util.stream.IntStream", "concat"): "IntStream",
|
|
1204
|
+
("java.util.stream.IntStream", "empty"): "IntStream",
|
|
1205
|
+
("java.util.stream.LongStream", "of"): "LongStream",
|
|
1206
|
+
("java.util.stream.LongStream", "iterate"): "LongStream",
|
|
1207
|
+
("java.util.stream.LongStream", "generate"): "LongStream",
|
|
1208
|
+
("java.util.stream.LongStream", "concat"): "LongStream",
|
|
1209
|
+
("java.util.stream.DoubleStream", "of"): "DoubleStream",
|
|
1210
|
+
("java.util.stream.DoubleStream", "iterate"): "DoubleStream",
|
|
1211
|
+
("java.util.stream.DoubleStream", "generate"): "DoubleStream",
|
|
1212
|
+
("java.lang.reflect.Modifier", "isPublic"): "boolean",
|
|
1213
|
+
("java.lang.reflect.Modifier", "isPrivate"): "boolean",
|
|
1214
|
+
("java.lang.reflect.Modifier", "isProtected"): "boolean",
|
|
1215
|
+
("java.lang.reflect.Modifier", "isStatic"): "boolean",
|
|
1216
|
+
("java.lang.reflect.Modifier", "isFinal"): "boolean",
|
|
1217
|
+
("java.lang.reflect.Modifier", "isAbstract"): "boolean",
|
|
1218
|
+
("java.lang.reflect.Modifier", "isInterface"): "boolean",
|
|
1219
|
+
("java.lang.reflect.Modifier", "isNative"): "boolean",
|
|
1220
|
+
("java.lang.reflect.Modifier", "isSynchronized"): "boolean",
|
|
1221
|
+
("java.lang.reflect.Modifier", "isTransient"): "boolean",
|
|
1222
|
+
("java.lang.reflect.Modifier", "isVolatile"): "boolean",
|
|
1223
|
+
("java.lang.reflect.Modifier", "toString"): "String",
|
|
1224
|
+
("java.util.Objects", "equals"): "boolean",
|
|
1225
|
+
("java.util.Objects", "deepEquals"): "boolean",
|
|
1226
|
+
("java.util.Objects", "isNull"): "boolean",
|
|
1227
|
+
("java.util.Objects", "nonNull"): "boolean",
|
|
1228
|
+
("java.util.Objects", "hash"): "int",
|
|
1229
|
+
("java.util.Objects", "hashCode"): "int",
|
|
1230
|
+
("java.util.Objects", "toString"): "String",
|
|
1231
|
+
("java.util.Arrays", "equals"): "boolean",
|
|
1232
|
+
("java.util.Arrays", "deepEquals"): "boolean",
|
|
1233
|
+
("java.util.Arrays", "toString"): "String",
|
|
1234
|
+
("java.util.Arrays", "deepToString"): "String",
|
|
1235
|
+
("java.util.Arrays", "hashCode"): "int",
|
|
1236
|
+
("java.util.Arrays", "deepHashCode"): "int",
|
|
1237
|
+
("java.util.Collections", "disjoint"): "boolean",
|
|
1238
|
+
("java.util.Collections", "addAll"): "boolean",
|
|
1239
|
+
("java.util.Collections", "frequency"): "int",
|
|
1240
|
+
("java.util.regex.Pattern", "compile"): "java.util.regex.Pattern",
|
|
1241
|
+
("java.util.regex.Pattern", "matches"): "boolean",
|
|
1242
|
+
("java.util.regex.Pattern", "quote"): "String",
|
|
1243
|
+
("java.nio.file.Path", "of"): "Path",
|
|
1244
|
+
("java.nio.file.Files", "createFile"): "Path",
|
|
1245
|
+
("java.nio.file.Files", "createDirectory"): "Path",
|
|
1246
|
+
("java.nio.file.Files", "createDirectories"): "Path",
|
|
1247
|
+
("java.nio.file.Files", "createTempFile"): "Path",
|
|
1248
|
+
("java.nio.file.Files", "createTempDirectory"): "Path",
|
|
1249
|
+
("java.nio.file.Files", "write"): "Path",
|
|
1250
|
+
("java.nio.file.Files", "writeString"): "Path",
|
|
1251
|
+
("java.nio.file.Files", "copy"): "Path",
|
|
1252
|
+
("java.nio.file.Files", "move"): "Path",
|
|
1253
|
+
("java.nio.file.Files", "walk"): "Stream<Path>",
|
|
1254
|
+
("java.nio.file.Files", "list"): "Stream<Path>",
|
|
1255
|
+
("java.nio.file.Files", "getLastModifiedTime"): "java.nio.file.attribute.FileTime",
|
|
1256
|
+
# Every overload of Spring's `ClassUtils.getPackageName` (`Class<?>` or
|
|
1257
|
+
# `String` FQN) is fixed to `String` regardless of the argument. Needed
|
|
1258
|
+
# for overload narrowing (E3, JAVA_METRICS_SPRING_MODULITH_PRECISION_SAMPLE.md):
|
|
1259
|
+
# `PackageName.of(ClassUtils.getPackageName(type))` fanned out between
|
|
1260
|
+
# `of(String)`/`of(String[])` because the nested call's return type was
|
|
1261
|
+
# unknown to the narrowing pass.
|
|
1262
|
+
("org.springframework.util.ClassUtils", "getPackageName"): "String",
|
|
1263
|
+
("org.springframework.util.ClassUtils", "resolveClassName"): "Class",
|
|
1264
|
+
# Spring's AOP helpers return a JDK Class even though their declarations
|
|
1265
|
+
# live outside the analyzed source. Without this exact external contract,
|
|
1266
|
+
# `var listenerType = AopUtils.getTargetClass(initializer)` leaves
|
|
1267
|
+
# `listenerType` unknown and later overload calls fan out across
|
|
1268
|
+
# `of(Class)`/`of(JavaClass)`-style siblings.
|
|
1269
|
+
("org.springframework.aop.support.AopUtils", "getTargetClass"): "Class",
|
|
1270
|
+
}
|
|
1271
|
+
# Batch 24: declared types of a small set of external (JDK) static
|
|
1272
|
+
# constants, FQN-keyed exactly like `JAVA_STATIC_METHOD_STUB_RETURNS` so a
|
|
1273
|
+
# source class that shares the simple name is never stubbed. Used only by
|
|
1274
|
+
# overload-argument narrowing (`_external_static_field_arg_type`):
|
|
1275
|
+
# `assertEquals(Integer.MAX_VALUE, parseFastForwardLimit(...))` fanned out
|
|
1276
|
+
# across every numeric `assertEquals` overload, and `LogRecordListener.stream
|
|
1277
|
+
# (Level.WARNING)` between `stream(Level)`/`stream(Class)`.
|
|
1278
|
+
# Simple names of the JDK `Throwable` family: a source exception class
|
|
1279
|
+
# extending any of these inherits `Throwable`'s members (JLS 8.4.8), so the
|
|
1280
|
+
# `("Throwable", member)` facts above apply to it when its own hierarchy
|
|
1281
|
+
# declares no member of that name.
|
|
1282
|
+
JAVA_THROWABLE_SIMPLE_TYPES: FrozenSet[str] = frozenset({
|
|
1283
|
+
"Throwable", "Exception", "RuntimeException", "Error", "AssertionError",
|
|
1284
|
+
"IllegalArgumentException", "IllegalStateException",
|
|
1285
|
+
"UnsupportedOperationException", "NullPointerException",
|
|
1286
|
+
"IndexOutOfBoundsException", "ArithmeticException", "ClassCastException",
|
|
1287
|
+
"NumberFormatException", "SecurityException", "IOException",
|
|
1288
|
+
"UncheckedIOException", "InterruptedException", "ExecutionException",
|
|
1289
|
+
"TimeoutException", "ReflectiveOperationException",
|
|
1290
|
+
"ClassNotFoundException", "NoSuchMethodException", "NoSuchFieldException",
|
|
1291
|
+
"IllegalAccessException", "InstantiationException",
|
|
1292
|
+
"InvocationTargetException", "CloneNotSupportedException", "LinkageError",
|
|
1293
|
+
})
|
|
1294
|
+
JAVA_STATIC_FIELD_STUB_TYPES: Dict[Tuple[str, str], str] = {
|
|
1295
|
+
("java.lang.Double", "MIN_NORMAL"): "double",
|
|
1296
|
+
("java.lang.Float", "MIN_NORMAL"): "float",
|
|
1297
|
+
("java.lang.Double", "MAX_EXPONENT"): "int",
|
|
1298
|
+
("java.lang.Double", "MIN_EXPONENT"): "int",
|
|
1299
|
+
("java.lang.Float", "MAX_EXPONENT"): "int",
|
|
1300
|
+
("java.lang.Float", "MIN_EXPONENT"): "int",
|
|
1301
|
+
("java.lang.Integer", "SIZE"): "int",
|
|
1302
|
+
("java.lang.Integer", "BYTES"): "int",
|
|
1303
|
+
("java.lang.Long", "SIZE"): "int",
|
|
1304
|
+
("java.lang.Long", "BYTES"): "int",
|
|
1305
|
+
("java.lang.Double", "SIZE"): "int",
|
|
1306
|
+
("java.lang.Double", "BYTES"): "int",
|
|
1307
|
+
("java.lang.Float", "SIZE"): "int",
|
|
1308
|
+
("java.lang.Float", "BYTES"): "int",
|
|
1309
|
+
("java.lang.Short", "SIZE"): "int",
|
|
1310
|
+
("java.lang.Byte", "SIZE"): "int",
|
|
1311
|
+
("java.lang.Character", "SIZE"): "int",
|
|
1312
|
+
**{("java.lang.Integer", name): "int" for name in ("MAX_VALUE", "MIN_VALUE", "SIZE", "BYTES")},
|
|
1313
|
+
**{("java.lang.Long", name): "long" for name in ("MAX_VALUE", "MIN_VALUE")},
|
|
1314
|
+
**{("java.lang.Short", name): "short" for name in ("MAX_VALUE", "MIN_VALUE")},
|
|
1315
|
+
**{("java.lang.Byte", name): "byte" for name in ("MAX_VALUE", "MIN_VALUE")},
|
|
1316
|
+
**{("java.lang.Character", name): "char" for name in ("MAX_VALUE", "MIN_VALUE")},
|
|
1317
|
+
**{("java.lang.Double", name): "double" for name in (
|
|
1318
|
+
"MAX_VALUE", "MIN_VALUE", "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY",
|
|
1319
|
+
)},
|
|
1320
|
+
**{("java.lang.Float", name): "float" for name in (
|
|
1321
|
+
"MAX_VALUE", "MIN_VALUE", "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY",
|
|
1322
|
+
)},
|
|
1323
|
+
("java.lang.Boolean", "TRUE"): "Boolean",
|
|
1324
|
+
("java.lang.Boolean", "FALSE"): "Boolean",
|
|
1325
|
+
**{("java.util.logging.Level", name): "java.util.logging.Level" for name in (
|
|
1326
|
+
"OFF", "SEVERE", "WARNING", "INFO", "CONFIG", "FINE", "FINER", "FINEST", "ALL",
|
|
1327
|
+
)},
|
|
1328
|
+
**{("java.nio.charset.StandardCharsets", name): "java.nio.charset.Charset" for name in (
|
|
1329
|
+
"UTF_8", "UTF_16", "UTF_16BE", "UTF_16LE", "US_ASCII", "ISO_8859_1",
|
|
1330
|
+
)},
|
|
1331
|
+
**{("java.util.concurrent.TimeUnit", name): "java.util.concurrent.TimeUnit" for name in (
|
|
1332
|
+
"NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS",
|
|
1333
|
+
)},
|
|
1334
|
+
**{("java.util.Locale", name): "java.util.Locale" for name in (
|
|
1335
|
+
"ROOT", "ENGLISH", "US", "UK", "GERMAN", "GERMANY", "FRENCH", "FRANCE",
|
|
1336
|
+
)},
|
|
1337
|
+
}
|
|
1338
|
+
# JLS 4.3.2: every class inherits these zero-argument `Object` members and an
|
|
1339
|
+
# override cannot change their erased return type, so the invocation result is
|
|
1340
|
+
# known for any receiver, even an unresolvable one.
|
|
1341
|
+
JAVA_OBJECT_MEMBER_RETURNS: Dict[str, str] = {
|
|
1342
|
+
"toString": "String",
|
|
1343
|
+
"hashCode": "int",
|
|
1344
|
+
"getClass": "Class",
|
|
1345
|
+
}
|
|
1346
|
+
# `java.time`'s immutable value types are fluent builders: every `plus*`/
|
|
1347
|
+
# `minus*`/`with*` mutator and `truncatedTo` is JavaDoc-guaranteed to return
|
|
1348
|
+
# the exact same type as the receiver — not a guess, a fixed JDK contract —
|
|
1349
|
+
# yet none of it lives in analyzed source, so a chain like
|
|
1350
|
+
# `now().minusHours(1)` used to go unknown past the first hop and force an
|
|
1351
|
+
# otherwise-resolvable sibling-overload call into P4.4's ambiguous fan-out
|
|
1352
|
+
# (`Moments.everyHour()`'s `emitEventsFor(now().minusHours(1))` fanning out
|
|
1353
|
+
# to both `emitEventsFor(LocalDateTime)` and `emitEventsFor(LocalDate)`,
|
|
1354
|
+
# wrongly reaching `DayHasPassed.of` — spring-modulith benchmark finding).
|
|
1355
|
+
JAVA_TIME_TEMPORAL_TYPES: FrozenSet[str] = frozenset({
|
|
1356
|
+
"LocalDate", "LocalDateTime", "LocalTime", "Instant", "ZonedDateTime",
|
|
1357
|
+
"OffsetDateTime", "OffsetTime", "Duration", "Period", "Year", "YearMonth",
|
|
1358
|
+
"MonthDay",
|
|
1359
|
+
})
|
|
1360
|
+
JAVA_TIME_SELF_RETURNING_PREFIXES: Tuple[str, ...] = ("plus", "minus", "with")
|
|
1361
|
+
JAVA_TIME_SELF_RETURNING_EXACT: FrozenSet[str] = frozenset({"truncatedTo"})
|
|
1362
|
+
# A handful of zero-arg, single-overload cross-type conversions with one
|
|
1363
|
+
# fixed JDK-declared return type. Deliberately excludes any method with a
|
|
1364
|
+
# same-name overload whose return type differs by arity or argument type
|
|
1365
|
+
# (`LocalDate.atStartOfDay()` -> LocalDateTime vs.
|
|
1366
|
+
# `atStartOfDay(ZoneId)` -> ZonedDateTime stays unresolved rather than
|
|
1367
|
+
# guessed at the wrong overload).
|
|
1368
|
+
JAVA_TIME_CONVERSION_RETURNS: Dict[Tuple[str, str], str] = {
|
|
1369
|
+
("LocalDateTime", "toLocalDate"): "LocalDate",
|
|
1370
|
+
("LocalDateTime", "toLocalTime"): "LocalTime",
|
|
1371
|
+
("ZonedDateTime", "toLocalDate"): "LocalDate",
|
|
1372
|
+
("ZonedDateTime", "toLocalDateTime"): "LocalDateTime",
|
|
1373
|
+
("ZonedDateTime", "toLocalTime"): "LocalTime",
|
|
1374
|
+
("ZonedDateTime", "toInstant"): "Instant",
|
|
1375
|
+
("OffsetDateTime", "toLocalDate"): "LocalDate",
|
|
1376
|
+
("OffsetDateTime", "toLocalDateTime"): "LocalDateTime",
|
|
1377
|
+
("OffsetDateTime", "toLocalTime"): "LocalTime",
|
|
1378
|
+
("OffsetDateTime", "toInstant"): "Instant",
|
|
1379
|
+
}
|
|
1380
|
+
# `BeanFactory.getBean(Class<T>)` (and its context/test-runner subtypes)
|
|
1381
|
+
# returns exactly the argument's own `Class<T>` literal type — documented
|
|
1382
|
+
# Spring Framework contract, not a guess — but none of these interfaces have
|
|
1383
|
+
# source in an analyzed project, so `ctxt.getBean(Foo.class)` used to leave
|
|
1384
|
+
# the call's result unknown even when `Foo` itself is a source class
|
|
1385
|
+
# (spring-modulith benchmark finding: `KafkaEventExternalizerConfiguration
|
|
1386
|
+
# IntegrationTests`'s `ctxt.getBean(DelegatingEventExternalizer.class)`
|
|
1387
|
+
# never resolved, hiding 3 real transitive callers behind it). Deliberately
|
|
1388
|
+
# excludes `getBean(String)`/`getBean(String, Class<T>)` string-named lookup
|
|
1389
|
+
# and multi-arg constructor-arg forms; only the exact single-`Class<T>`-
|
|
1390
|
+
# literal overload has one unambiguous, name-independent target.
|
|
1391
|
+
SPRING_BEAN_CONTAINER_TYPES: FrozenSet[str] = frozenset({
|
|
1392
|
+
"BeanFactory", "ListableBeanFactory", "ConfigurableListableBeanFactory",
|
|
1393
|
+
"ApplicationContext", "ConfigurableApplicationContext",
|
|
1394
|
+
"WebApplicationContext", "ConfigurableWebApplicationContext",
|
|
1395
|
+
"AssertableApplicationContext", "AssertableWebApplicationContext",
|
|
1396
|
+
"AssertableReactiveWebApplicationContext",
|
|
1397
|
+
})
|
|
1398
|
+
# Spring Boot Test's `AbstractApplicationContextRunner.run(ContextConsumer<?
|
|
1399
|
+
# super A>)` target-types its lambda/method-reference argument's single
|
|
1400
|
+
# parameter as the runner's own fixed assertable-context type `A` — a
|
|
1401
|
+
# documented, non-generic-inferred contract per runner subclass (each
|
|
1402
|
+
# subclass hard-codes its own `A`), not a project fact. None of these
|
|
1403
|
+
# classes have source in an analyzed project, so a lambda passed to `.run`
|
|
1404
|
+
# used to leave its parameter's type completely unknown (see
|
|
1405
|
+
# `SPRING_BEAN_CONTAINER_TYPES` above for why that mattered here).
|
|
1406
|
+
SPRING_CONTEXT_RUNNER_ASSERTABLE_CONTEXT: Dict[str, str] = {
|
|
1407
|
+
"ApplicationContextRunner": "AssertableApplicationContext",
|
|
1408
|
+
"WebApplicationContextRunner": "AssertableWebApplicationContext",
|
|
1409
|
+
"ReactiveWebApplicationContextRunner": "AssertableReactiveWebApplicationContext",
|
|
1410
|
+
}
|
|
1411
|
+
# SAM parameter tables for a small set of well-known *external*
|
|
1412
|
+
# (non-JDK) functional interfaces, kept deliberately separate from
|
|
1413
|
+
# `_JDK_SAM_PARAMS`/`_JDK_SAM_RETURNS` above so that table's "derivable
|
|
1414
|
+
# without indexing JDK sources" invariant stays exactly JDK-only.
|
|
1415
|
+
# `ContextConsumer<C>`'s single abstract method is
|
|
1416
|
+
# `void accept(C context) throws Throwable` (Spring Boot Test).
|
|
1417
|
+
EXTERNAL_SAM_PARAMS: Dict[str, Tuple[Union[int, str], ...]] = {
|
|
1418
|
+
"ContextConsumer": (0,),
|
|
1419
|
+
}
|
|
1420
|
+
EXTERNAL_SAM_RETURNS: Dict[str, Union[int, str]] = {
|
|
1421
|
+
"ContextConsumer": "void",
|
|
1422
|
+
}
|
|
1423
|
+
# Small, exact JDK hierarchy facts used only when both sides resolve through
|
|
1424
|
+
# their file's explicit import context. This is not a simple-name fallback:
|
|
1425
|
+
# a project-local `HashMap` never matches `java.util.HashMap` here.
|
|
1426
|
+
JAVA_EXTERNAL_SUBTYPE_STUBS: FrozenSet[Tuple[str, str]] = frozenset({
|
|
1427
|
+
# Batch 25: the JDK types the new fixed-return facts and static
|
|
1428
|
+
# factories can now put *into* an argument position (`Arrays.asList(..)`
|
|
1429
|
+
# -> `List`, `EnumSet.of(..)`, `Stack`, reflection/concurrency
|
|
1430
|
+
# receivers, `Throwable.getCause()`), each with the supertypes a
|
|
1431
|
+
# declared parameter is commonly spelled as. A newly typed argument
|
|
1432
|
+
# that cannot reach its parameter here is a dropped candidate (FN),
|
|
1433
|
+
# not an unknown, so every producible type needs its ancestry listed.
|
|
1434
|
+
("java.util.List", "java.util.SequencedCollection"),
|
|
1435
|
+
("java.util.ArrayList", "java.lang.Iterable"),
|
|
1436
|
+
("java.util.LinkedList", "java.util.List"),
|
|
1437
|
+
("java.util.LinkedList", "java.util.Collection"),
|
|
1438
|
+
("java.util.LinkedList", "java.lang.Iterable"),
|
|
1439
|
+
("java.util.LinkedList", "java.util.Deque"),
|
|
1440
|
+
("java.util.LinkedList", "java.util.Queue"),
|
|
1441
|
+
("java.util.Stack", "java.util.Vector"),
|
|
1442
|
+
("java.util.Stack", "java.util.List"),
|
|
1443
|
+
("java.util.Stack", "java.util.Collection"),
|
|
1444
|
+
("java.util.Stack", "java.lang.Iterable"),
|
|
1445
|
+
("java.util.Vector", "java.util.List"),
|
|
1446
|
+
("java.util.Vector", "java.util.Collection"),
|
|
1447
|
+
("java.util.Vector", "java.lang.Iterable"),
|
|
1448
|
+
("java.util.HashSet", "java.util.Collection"),
|
|
1449
|
+
("java.util.HashSet", "java.lang.Iterable"),
|
|
1450
|
+
("java.util.LinkedHashSet", "java.util.Set"),
|
|
1451
|
+
("java.util.LinkedHashSet", "java.util.Collection"),
|
|
1452
|
+
("java.util.LinkedHashSet", "java.lang.Iterable"),
|
|
1453
|
+
("java.util.TreeSet", "java.util.Set"),
|
|
1454
|
+
("java.util.TreeSet", "java.util.SortedSet"),
|
|
1455
|
+
("java.util.TreeSet", "java.util.NavigableSet"),
|
|
1456
|
+
("java.util.TreeSet", "java.util.Collection"),
|
|
1457
|
+
("java.util.TreeSet", "java.lang.Iterable"),
|
|
1458
|
+
("java.util.SortedSet", "java.util.Set"),
|
|
1459
|
+
("java.util.SortedSet", "java.util.Collection"),
|
|
1460
|
+
("java.util.SortedSet", "java.lang.Iterable"),
|
|
1461
|
+
("java.util.EnumSet", "java.util.Set"),
|
|
1462
|
+
("java.util.EnumSet", "java.util.Collection"),
|
|
1463
|
+
("java.util.EnumSet", "java.lang.Iterable"),
|
|
1464
|
+
("java.util.ArrayDeque", "java.util.Collection"),
|
|
1465
|
+
("java.util.ArrayDeque", "java.lang.Iterable"),
|
|
1466
|
+
("java.util.Deque", "java.util.Queue"),
|
|
1467
|
+
("java.util.Deque", "java.util.Collection"),
|
|
1468
|
+
("java.util.Deque", "java.lang.Iterable"),
|
|
1469
|
+
("java.util.Queue", "java.util.Collection"),
|
|
1470
|
+
("java.util.Queue", "java.lang.Iterable"),
|
|
1471
|
+
("java.util.concurrent.ConcurrentHashMap", "java.util.Map"),
|
|
1472
|
+
("java.util.concurrent.ConcurrentHashMap", "java.util.concurrent.ConcurrentMap"),
|
|
1473
|
+
("java.util.concurrent.ConcurrentMap", "java.util.Map"),
|
|
1474
|
+
("java.util.regex.Matcher", "java.util.regex.MatchResult"),
|
|
1475
|
+
("java.util.concurrent.locks.ReentrantLock", "java.util.concurrent.locks.Lock"),
|
|
1476
|
+
("java.util.concurrent.ForkJoinPool", "java.util.concurrent.ExecutorService"),
|
|
1477
|
+
("java.util.concurrent.ForkJoinPool", "java.util.concurrent.Executor"),
|
|
1478
|
+
("java.util.concurrent.ThreadPoolExecutor", "java.util.concurrent.ExecutorService"),
|
|
1479
|
+
("java.util.concurrent.ThreadPoolExecutor", "java.util.concurrent.Executor"),
|
|
1480
|
+
("java.util.concurrent.ScheduledExecutorService", "java.util.concurrent.ExecutorService"),
|
|
1481
|
+
("java.util.concurrent.ScheduledExecutorService", "java.util.concurrent.Executor"),
|
|
1482
|
+
("java.util.concurrent.ExecutorService", "java.util.concurrent.Executor"),
|
|
1483
|
+
("java.util.concurrent.CompletableFuture", "java.util.concurrent.Future"),
|
|
1484
|
+
("java.util.concurrent.CompletableFuture", "java.util.concurrent.CompletionStage"),
|
|
1485
|
+
("java.lang.Thread", "java.lang.Runnable"),
|
|
1486
|
+
("java.lang.reflect.Method", "java.lang.reflect.Executable"),
|
|
1487
|
+
("java.lang.reflect.Method", "java.lang.reflect.AccessibleObject"),
|
|
1488
|
+
("java.lang.reflect.Method", "java.lang.reflect.Member"),
|
|
1489
|
+
("java.lang.reflect.Method", "java.lang.reflect.AnnotatedElement"),
|
|
1490
|
+
("java.lang.reflect.Constructor", "java.lang.reflect.Executable"),
|
|
1491
|
+
("java.lang.reflect.Constructor", "java.lang.reflect.AccessibleObject"),
|
|
1492
|
+
("java.lang.reflect.Constructor", "java.lang.reflect.Member"),
|
|
1493
|
+
("java.lang.reflect.Constructor", "java.lang.reflect.AnnotatedElement"),
|
|
1494
|
+
("java.lang.reflect.Executable", "java.lang.reflect.AccessibleObject"),
|
|
1495
|
+
("java.lang.reflect.Executable", "java.lang.reflect.Member"),
|
|
1496
|
+
("java.lang.reflect.Executable", "java.lang.reflect.AnnotatedElement"),
|
|
1497
|
+
("java.lang.reflect.Field", "java.lang.reflect.AccessibleObject"),
|
|
1498
|
+
("java.lang.reflect.Field", "java.lang.reflect.Member"),
|
|
1499
|
+
("java.lang.reflect.Field", "java.lang.reflect.AnnotatedElement"),
|
|
1500
|
+
("java.lang.reflect.Parameter", "java.lang.reflect.AnnotatedElement"),
|
|
1501
|
+
("java.lang.Class", "java.lang.reflect.AnnotatedElement"),
|
|
1502
|
+
("java.lang.Class", "java.lang.reflect.Type"),
|
|
1503
|
+
("java.lang.Class", "java.lang.reflect.GenericDeclaration"),
|
|
1504
|
+
("java.lang.Module", "java.lang.reflect.AnnotatedElement"),
|
|
1505
|
+
("java.io.File", "java.lang.Comparable"),
|
|
1506
|
+
("java.io.File", "java.io.Serializable"),
|
|
1507
|
+
("java.nio.file.Path", "java.lang.Comparable"),
|
|
1508
|
+
("java.nio.file.Path", "java.lang.Iterable"),
|
|
1509
|
+
("java.nio.file.Path", "java.nio.file.Watchable"),
|
|
1510
|
+
("java.lang.IllegalArgumentException", "java.lang.RuntimeException"),
|
|
1511
|
+
("java.lang.IllegalArgumentException", "java.lang.Exception"),
|
|
1512
|
+
("java.lang.IllegalArgumentException", "java.lang.Throwable"),
|
|
1513
|
+
("java.lang.IllegalStateException", "java.lang.RuntimeException"),
|
|
1514
|
+
("java.lang.IllegalStateException", "java.lang.Exception"),
|
|
1515
|
+
("java.lang.IllegalStateException", "java.lang.Throwable"),
|
|
1516
|
+
("java.lang.UnsupportedOperationException", "java.lang.RuntimeException"),
|
|
1517
|
+
("java.lang.UnsupportedOperationException", "java.lang.Exception"),
|
|
1518
|
+
("java.lang.UnsupportedOperationException", "java.lang.Throwable"),
|
|
1519
|
+
("java.io.IOException", "java.lang.Exception"),
|
|
1520
|
+
("java.io.UncheckedIOException", "java.lang.RuntimeException"),
|
|
1521
|
+
("java.io.UncheckedIOException", "java.lang.Exception"),
|
|
1522
|
+
("java.io.UncheckedIOException", "java.lang.Throwable"),
|
|
1523
|
+
("java.lang.InterruptedException", "java.lang.Exception"),
|
|
1524
|
+
("java.lang.InterruptedException", "java.lang.Throwable"),
|
|
1525
|
+
("java.util.concurrent.ExecutionException", "java.lang.Exception"),
|
|
1526
|
+
("java.util.concurrent.ExecutionException", "java.lang.Throwable"),
|
|
1527
|
+
("java.util.concurrent.TimeoutException", "java.lang.Exception"),
|
|
1528
|
+
("java.util.concurrent.TimeoutException", "java.lang.Throwable"),
|
|
1529
|
+
("java.lang.ReflectiveOperationException", "java.lang.Exception"),
|
|
1530
|
+
("java.lang.ReflectiveOperationException", "java.lang.Throwable"),
|
|
1531
|
+
("java.lang.ClassNotFoundException", "java.lang.ReflectiveOperationException"),
|
|
1532
|
+
("java.lang.ClassNotFoundException", "java.lang.Exception"),
|
|
1533
|
+
("java.lang.ClassNotFoundException", "java.lang.Throwable"),
|
|
1534
|
+
("java.lang.NoSuchMethodException", "java.lang.ReflectiveOperationException"),
|
|
1535
|
+
("java.lang.NoSuchMethodException", "java.lang.Exception"),
|
|
1536
|
+
("java.lang.NoSuchMethodException", "java.lang.Throwable"),
|
|
1537
|
+
("java.lang.reflect.InvocationTargetException", "java.lang.ReflectiveOperationException"),
|
|
1538
|
+
("java.lang.reflect.InvocationTargetException", "java.lang.Exception"),
|
|
1539
|
+
("java.lang.reflect.InvocationTargetException", "java.lang.Throwable"),
|
|
1540
|
+
("java.io.StringReader", "java.io.Reader"),
|
|
1541
|
+
("java.lang.String", "java.lang.CharSequence"),
|
|
1542
|
+
("java.util.ArrayList", "java.util.List"),
|
|
1543
|
+
("java.util.ArrayList", "java.util.Collection"),
|
|
1544
|
+
("java.util.ArrayDeque", "java.util.Deque"),
|
|
1545
|
+
("java.util.ArrayDeque", "java.util.Queue"),
|
|
1546
|
+
("java.util.HashMap", "java.util.Map"),
|
|
1547
|
+
("java.util.LinkedHashMap", "java.util.Map"),
|
|
1548
|
+
("java.util.TreeMap", "java.util.Map"),
|
|
1549
|
+
("java.util.HashSet", "java.util.Set"),
|
|
1550
|
+
("java.util.List", "java.util.Collection"),
|
|
1551
|
+
("java.util.List", "java.lang.Iterable"),
|
|
1552
|
+
("java.util.Set", "java.util.Collection"),
|
|
1553
|
+
("java.util.Set", "java.lang.Iterable"),
|
|
1554
|
+
("java.util.Collection", "java.lang.Iterable"),
|
|
1555
|
+
("java.util.concurrent.LinkedBlockingQueue", "java.util.concurrent.BlockingQueue"),
|
|
1556
|
+
("java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy", "java.util.concurrent.RejectedExecutionHandler"),
|
|
1557
|
+
("java.lang.Exception", "java.lang.Throwable"),
|
|
1558
|
+
("java.lang.RuntimeException", "java.lang.Throwable"),
|
|
1559
|
+
("java.lang.RuntimeException", "java.lang.Exception"),
|
|
1560
|
+
("java.lang.Error", "java.lang.Throwable"),
|
|
1561
|
+
("java.lang.LinkageError", "java.lang.Error"),
|
|
1562
|
+
("java.lang.LinkageError", "java.lang.Throwable"),
|
|
1563
|
+
("java.lang.AssertionError", "java.lang.Error"),
|
|
1564
|
+
("java.lang.AssertionError", "java.lang.Throwable"),
|
|
1565
|
+
("java.lang.NullPointerException", "java.lang.RuntimeException"),
|
|
1566
|
+
("java.lang.NullPointerException", "java.lang.Exception"),
|
|
1567
|
+
("java.lang.NullPointerException", "java.lang.Throwable"),
|
|
1568
|
+
("java.io.IOException", "java.lang.Throwable"),
|
|
1569
|
+
("java.io.UnsupportedEncodingException", "java.io.IOException"),
|
|
1570
|
+
("java.io.UnsupportedEncodingException", "java.lang.Throwable"),
|
|
1571
|
+
("java.lang.CloneNotSupportedException", "java.lang.Exception"),
|
|
1572
|
+
("java.lang.CloneNotSupportedException", "java.lang.Throwable"),
|
|
1573
|
+
("java.lang.IllegalAccessException", "java.lang.Throwable"),
|
|
1574
|
+
("java.lang.InterruptedException", "java.lang.Throwable"),
|
|
1575
|
+
("java.net.URISyntaxException", "java.lang.Throwable"),
|
|
1576
|
+
("java.lang.Class", "java.lang.reflect.AnnotatedElement"),
|
|
1577
|
+
("java.lang.reflect.Constructor", "java.lang.reflect.AnnotatedElement"),
|
|
1578
|
+
("java.lang.reflect.Constructor", "java.lang.reflect.Member"),
|
|
1579
|
+
# JDK reflection hierarchy: both Method and Constructor extend
|
|
1580
|
+
# Executable. This lets an exactly typed Method select a source overload
|
|
1581
|
+
# declared against Executable without treating unrelated Member values as
|
|
1582
|
+
# executable.
|
|
1583
|
+
("java.lang.reflect.Constructor", "java.lang.reflect.Executable"),
|
|
1584
|
+
("java.lang.reflect.Executable", "java.lang.reflect.AnnotatedElement"),
|
|
1585
|
+
("java.lang.reflect.Field", "java.lang.reflect.AnnotatedElement"),
|
|
1586
|
+
("java.lang.reflect.Field", "java.lang.reflect.Member"),
|
|
1587
|
+
("java.lang.reflect.Method", "java.lang.reflect.AnnotatedElement"),
|
|
1588
|
+
("java.lang.reflect.Method", "java.lang.reflect.Member"),
|
|
1589
|
+
("java.lang.reflect.Method", "java.lang.reflect.Executable"),
|
|
1590
|
+
})
|
|
1591
|
+
JAVA_EXTERNAL_TYPES = frozenset(name for relation in JAVA_EXTERNAL_SUBTYPE_STUBS for name in relation)
|
|
1592
|
+
# Concrete `java_type_kind`s that can carry a runtime method body — the only
|
|
1593
|
+
# ones eligible to be a fan-out/DI target (an `interface`/`abstract class`
|
|
1594
|
+
# receiver is the *source* of the ambiguity, never a resolved target).
|
|
1595
|
+
_CONCRETE_TYPE_KINDS: FrozenSet[str] = frozenset({"class", "record", "enum"})
|
|
1596
|
+
|
|
1597
|
+
# Precision↔recall dial (deep-dive §6.3), mirroring P2.21's `DRIFT_RECALL_MODE`.
|
|
1598
|
+
# `strict` keeps only the interface-declaration edge (P4.4's own result);
|
|
1599
|
+
# `balanced` (default, precision-first) fans out to concrete implementors but
|
|
1600
|
+
# caps emission above `_FANOUT_CAP` to avoid flooding; `recall` fans out to
|
|
1601
|
+
# every implementor as a low-confidence candidate regardless of count.
|
|
1602
|
+
_FANOUT_MODES = ("strict", "balanced", "recall")
|
|
1603
|
+
_DEFAULT_FANOUT_MODE = "balanced"
|
|
1604
|
+
_DEFAULT_FANOUT_CAP = 5
|
|
1605
|
+
|
|
1606
|
+
# Per-edge confidence for each fan-out/DI strategy — the evidence table in
|
|
1607
|
+
# codegraph-java-deep-dive.md §6.3 / PROBLEMS.md P4.12. A single implementor is
|
|
1608
|
+
# effectively concrete (High band); many implementors are honest ambiguity
|
|
1609
|
+
# (Low band, <0.6). DI evidence tightens the score toward concrete.
|
|
1610
|
+
_CONF_SINGLE_IMPLEMENTOR = 0.85
|
|
1611
|
+
_CONF_MULTI_IMPLEMENTOR = 0.45
|
|
1612
|
+
_CONF_DI_SINGLE_COMPONENT = 0.85
|
|
1613
|
+
_CONF_SPRING_QUALIFIER = 0.95
|
|
1614
|
+
_CONF_SPRING_PRIMARY = 0.90
|
|
1615
|
+
|
|
1616
|
+
|
|
1617
|
+
# Matches the first string literal argument of an annotation, e.g.
|
|
1618
|
+
# `@Qualifier("stripe")` -> `stripe`, `@Service("fastPayment")` -> `fastPayment`.
|
|
1619
|
+
_ANNOTATION_STRING_ARG = re.compile(r'"((?:[^"\\]|\\.)*)"')
|