diff --git a/src/python/pants/backend/scala/dependency_inference/ScalaParser.scala b/src/python/pants/backend/scala/dependency_inference/ScalaParser.scala index 03906bcb22d..644f362491f 100644 --- a/src/python/pants/backend/scala/dependency_inference/ScalaParser.scala +++ b/src/python/pants/backend/scala/dependency_inference/ScalaParser.scala @@ -235,18 +235,20 @@ class SourceAnalysisTraverser extends Traverser { ) } - case Defn.Class(mods, nameNode, _tparams, ctor, templ) => { + case Defn.Class(mods, nameNode, tparams, ctor, templ) => { visitMods(mods) val name = extractName(nameNode) recordProvidedName(name, sawClass = true) + apply(tparams) apply(ctor) visitTemplate(templ, name) } - case Defn.Trait(mods, nameNode, _tparams, ctor, templ) => { + case Defn.Trait(mods, nameNode, tparams, ctor, templ) => { visitMods(mods) val name = extractName(nameNode) recordProvidedName(name, sawTrait = true) + apply(tparams) apply(ctor) visitTemplate(templ, name) } @@ -299,7 +301,7 @@ class SourceAnalysisTraverser extends Traverser { super.apply(rhs) } - case Defn.Def(mods, nameNode, _tparams, params, decltpe, body) => { + case Defn.Def(mods, nameNode, tparams, params, decltpe, body) => { visitMods(mods) val name = extractName(nameNode) recordProvidedName(name) @@ -308,14 +310,16 @@ class SourceAnalysisTraverser extends Traverser { extractNamesFromTypeTree(tpe).foreach(recordConsumedSymbol(_)) }) + apply(tparams) params.foreach(param => apply(param)) withSuppressProvidedNames(() => apply(body)) } - case Decl.Def(mods, _nameNode, _tparams, params, decltpe) => { + case Decl.Def(mods, _nameNode, tparams, params, decltpe) => { visitMods(mods) extractNamesFromTypeTree(decltpe).foreach(recordConsumedSymbol(_)) + apply(tparams) params.foreach(param => apply(param)) } @@ -366,6 +370,11 @@ class SourceAnalysisTraverser extends Traverser { }) } + case Type.Param(mods, _name, _tparams, bounds, _vbounds, _cbounds) => { + visitMods(mods) + extractNamesFromTypeTree(bounds).foreach(recordConsumedSymbol(_)) + } + case Ctor.Primary(mods, _name, params_list) => { visitMods(mods) params_list.foreach(params => { diff --git a/src/python/pants/backend/scala/dependency_inference/scala_parser_test.py b/src/python/pants/backend/scala/dependency_inference/scala_parser_test.py index a67f1b6d91e..c3f4023a555 100644 --- a/src/python/pants/backend/scala/dependency_inference/scala_parser_test.py +++ b/src/python/pants/backend/scala/dependency_inference/scala_parser_test.py @@ -593,3 +593,31 @@ def test_package_object_extends_trait(rule_runner: RuleRunner) -> None: ) assert sorted(analysis.fully_qualified_consumed_symbols()) == ["foo.Trait", "foo.bar.Trait"] + + +def test_type_constaint(rule_runner: RuleRunner) -> None: + analysis = _analyze( + rule_runner, + textwrap.dedent( + """\ + package foo + + trait Foo[T >: A <: B] + + class Bar[T >: C <: D] + + class Quxx { + def doSomething[T >: E <: F]() = () + } + """ + ), + ) + + assert sorted(analysis.fully_qualified_consumed_symbols()) == [ + "foo.A", + "foo.B", + "foo.C", + "foo.D", + "foo.E", + "foo.F", + ]