@@ -266,6 +266,113 @@ def _transitive_from_exports_test(name):
266266def _transitive_from_associates_test (name ):
267267 _abi_test (name , _transitive_from_associates_test_impl )
268268
269+ def _dep_infos_ordering_test_impl (env , target ):
270+ """Test that user deps take precedence over stdlib in dep_infos ordering.
271+
272+ This is a regression test for https://github.com/bazelbuild/rules_kotlin/issues/1368
273+ where the stdlib was placed first in the classpath, causing it to shadow user
274+ dependencies with conflicting classes (e.g., org.jetbrains.annotations.NotNull).
275+ """
276+ user_dep_java_info = JavaInfo (
277+ compile_jar = _file (env .ctx .attr .user_dep_jar ),
278+ output_jar = _file (env .ctx .attr .user_dep_jar ),
279+ )
280+
281+ associate_java_info = JavaInfo (
282+ compile_jar = _file (env .ctx .attr .associate_jar ),
283+ output_jar = _file (env .ctx .attr .associate_jar ),
284+ )
285+
286+ stdlib_java_info = JavaInfo (
287+ compile_jar = _file (env .ctx .attr .jvm_jar ),
288+ output_jar = _file (env .ctx .attr .jvm_jar ),
289+ )
290+
291+ associate_deps = [
292+ {
293+ JavaInfo : associate_java_info ,
294+ _KtJvmInfo : _KtJvmInfo (
295+ module_name = "associate_name" ,
296+ ),
297+ },
298+ ]
299+
300+ user_deps = [
301+ {
302+ JavaInfo : user_dep_java_info ,
303+ },
304+ ]
305+
306+ fake_ctx = struct (
307+ label = target .label ,
308+ attr = struct (
309+ module_name = "" ,
310+ tags = [],
311+ ),
312+ )
313+
314+ toolchains = struct (
315+ kt = struct (
316+ experimental_remove_private_classes_in_abi_jars = False ,
317+ experimental_prune_transitive_deps = False ,
318+ experimental_strict_associate_dependencies = False ,
319+ jvm_stdlibs = stdlib_java_info ,
320+ ),
321+ )
322+
323+ result = _jvm_deps_utils .jvm_deps (
324+ ctx = fake_ctx ,
325+ toolchains = toolchains ,
326+ associate_deps = associate_deps ,
327+ deps = user_deps ,
328+ )
329+
330+ # Assert the ordering: result.deps should be [user_deps, associates, stdlib]
331+ env .expect .that_int (len (result .deps )).equals (3 )
332+
333+ # Verify compile_jars contains all deps in correct order
334+ classpath_list = result .compile_jars .to_list ()
335+ user_dep_file = _file (env .ctx .attr .user_dep_jar )
336+ stdlib_file = _file (env .ctx .attr .jvm_jar )
337+
338+ # Find indices of user dep and stdlib in classpath
339+ user_dep_idx = - 1
340+ stdlib_idx = - 1
341+ for idx , jar in enumerate (classpath_list ):
342+ if jar == user_dep_file :
343+ user_dep_idx = idx
344+ if jar == stdlib_file :
345+ stdlib_idx = idx
346+
347+ # Both should be found
348+ env .expect .that_bool (user_dep_idx >= 0 ).equals (True )
349+ env .expect .that_bool (stdlib_idx >= 0 ).equals (True )
350+
351+ # User dep should come before stdlib in the classpath
352+ env .expect .that_bool (user_dep_idx < stdlib_idx ).equals (True )
353+
354+ def _dep_infos_ordering_test (name ):
355+ util .helper_target (
356+ native .filegroup ,
357+ name = name + "_subject" ,
358+ srcs = [],
359+ )
360+ analysis_test (
361+ name = name ,
362+ impl = _dep_infos_ordering_test_impl ,
363+ target = name + "_subject" ,
364+ attr_values = {
365+ "user_dep_jar" : util .empty_file (name + "user_dep.jar" ),
366+ "associate_jar" : util .empty_file (name + "associate.jar" ),
367+ "jvm_jar" : util .empty_file (name + "jvm.jar" ),
368+ },
369+ attrs = {
370+ "user_dep_jar" : attr .label (allow_files = True ),
371+ "associate_jar" : attr .label (allow_files = True ),
372+ "jvm_jar" : attr .label (allow_files = True ),
373+ },
374+ )
375+
269376def jvm_deps_test_suite (name ):
270377 test_suite (
271378 name ,
@@ -274,5 +381,6 @@ def jvm_deps_test_suite(name):
274381 _fat_abi_test ,
275382 _transitive_from_exports_test ,
276383 _transitive_from_associates_test ,
384+ _dep_infos_ordering_test ,
277385 ],
278386 )
0 commit comments