diff --git a/lib/modules/manager/gradle/extract.spec.ts b/lib/modules/manager/gradle/extract.spec.ts
index 43ee5438be915cebcade2b8d8a6b83a5ea3c40a7..a497da28611a25c0258f0a8247aba5bfdd5d4258 100644
--- a/lib/modules/manager/gradle/extract.spec.ts
+++ b/lib/modules/manager/gradle/extract.spec.ts
@@ -105,7 +105,8 @@ describe('modules/manager/gradle/extract', () => {
   it('works with file-ext-var', async () => {
     mockFs({
       'gradle.properties': 'baz=1.2.3',
-      'build.gradle': 'url "https://example.com"; "foo:bar:$baz@zip"',
+      'build.gradle':
+        'repositories { maven { url "https://example.com" } }; "foo:bar:$baz@zip"',
       'settings.gradle': null as never, // TODO: #7154
     });
 
@@ -171,10 +172,10 @@ describe('modules/manager/gradle/extract', () => {
   it('deduplicates registry urls', async () => {
     const fsMock = {
       'build.gradle': [
-        'url "https://repo.maven.apache.org/maven2"',
-        'url "https://repo.maven.apache.org/maven2"',
-        'url "https://example.com"',
-        'url "https://example.com"',
+        'repositories { maven { url "https://repo.maven.apache.org/maven2" } }',
+        'repositories { maven { url "https://repo.maven.apache.org/maven2" } }',
+        'repositories { maven { url "https://example.com" } }',
+        'repositories { maven { url "https://example.com" } }',
         'id "foo.bar" version "1.2.3"',
         '"foo:bar:1.2.3"',
       ].join(';\n'),
diff --git a/lib/modules/manager/gradle/parser.spec.ts b/lib/modules/manager/gradle/parser.spec.ts
index 896c2dd827598e500a5c78ee76bbabc78217d74d..c9a9eb457477bdcfe8e6962e3c35c5b34c954f12 100644
--- a/lib/modules/manager/gradle/parser.spec.ts
+++ b/lib/modules/manager/gradle/parser.spec.ts
@@ -32,129 +32,184 @@ describe('modules/manager/gradle/parser', () => {
     expect((await parseGradle('id "foo.bar" version')).deps).toBeEmpty();
   });
 
-  describe('variable assignments', () => {
-    test.each`
-      input                             | name                 | value
-      ${'version = "1.2.3"'}            | ${'version'}         | ${'1.2.3'}
-      ${'set("version", "1.2.3")'}      | ${'version'}         | ${'1.2.3'}
-      ${'versions.foobar = "1.2.3"'}    | ${'versions.foobar'} | ${'1.2.3'}
-      ${'ext.foobar = "1.2.3"'}         | ${'foobar'}          | ${'1.2.3'}
-      ${'project.foobar = "1.2.3"'}     | ${'foobar'}          | ${'1.2.3'}
-      ${'rootProject.foobar = "1.2.3"'} | ${'foobar'}          | ${'1.2.3'}
-    `('$input', async ({ input, name, value }) => {
-      const { vars } = await parseGradle(input);
-      expect(vars).toContainKey(name);
-      expect(vars[name]).toMatchObject({ key: name, value });
+  describe('variables', () => {
+    describe('Groovy: single var assignments', () => {
+      test.each`
+        input                              | name         | value
+        ${'foo = "1.2.3"'}                 | ${'foo'}     | ${'1.2.3'}
+        ${'foo.bar = "1.2.3"'}             | ${'foo.bar'} | ${'1.2.3'}
+        ${'ext.foobar = "1.2.3"'}          | ${'foobar'}  | ${'1.2.3'}
+        ${'project.foobar = "1.2.3"'}      | ${'foobar'}  | ${'1.2.3'}
+        ${'project.ext.foo.bar = "1.2.3"'} | ${'foo.bar'} | ${'1.2.3'}
+        ${'rootProject.foobar = "1.2.3"'}  | ${'foobar'}  | ${'1.2.3'}
+        ${'rootProject.foo.bar = "1.2.3"'} | ${'foo.bar'} | ${'1.2.3'}
+      `('$input', async ({ input, name, value }) => {
+        const { vars } = await parseGradle(input);
+        expect(vars).toContainKey(name);
+        expect(vars[name]).toMatchObject({ key: name, value });
+      });
+    });
+
+    describe('Kotlin: single var assignments', () => {
+      test.each`
+        input                        | name     | value
+        ${'set("foo", "1.2.3")'}     | ${'foo'} | ${'1.2.3'}
+        ${'version("foo", "1.2.3")'} | ${'foo'} | ${'1.2.3'}
+      `('$input', async ({ input, name, value }) => {
+        const { vars } = await parseGradle(input);
+        expect(vars).toContainKey(name);
+        expect(vars[name]).toMatchObject({ key: name, value });
+      });
     });
   });
 
   describe('dependencies', () => {
-    describe('simple cases', () => {
+    describe('simple dependency strings', () => {
       test.each`
-        input                                                                             | output
-        ${'group: "foo", name: "bar", version: "1.2.3"'}                                  | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
-        ${"implementation platform(group: 'foo', name: 'bar', version: '1.2.3')"}         | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
-        ${'group: "foo", name: "bar", version: depVersion'}                               | ${null}
-        ${'("foo", "bar", "1.2.3")'}                                                      | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
-        ${'(group = "foo", name = "bar", version = "1.2.3")'}                             | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
-        ${'"foo:bar:1.2.3@zip"'}                                                          | ${{ currentValue: '1.2.3', dataType: 'zip', depName: 'foo:bar' }}
-        ${'(group: "foo", name: "bar", version: "1.2.3", classifier: "sources")'}         | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
-        ${'(group: "foo", name: "bar", version: "1.2.3") {exclude module: "spring-jcl"}'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+        input                          | output
+        ${'"foo:bar:1.2.3"'}           | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+        ${'"foo:bar:1.2.3@zip"'}       | ${{ depName: 'foo:bar', currentValue: '1.2.3', dataType: 'zip' }}
+        ${'foo.bar = "foo:bar:1.2.3"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
       `('$input', async ({ input, output }) => {
         const { deps } = await parseGradle(input);
         expect(deps).toMatchObject([output].filter(Boolean));
       });
     });
 
-    describe('annoying methods', () => {
+    describe('interpolated dependency strings', () => {
       test.each`
-        input                                                        | output
-        ${'createXmlValueRemover("defaults", "integer", "integer")'} | ${{ depName: 'defaults:integer', currentValue: 'integer', skipReason: 'ignored' }}
-        ${'events("passed", "skipped", "failed")'}                   | ${{ depName: 'passed:skipped', currentValue: 'failed', skipReason: 'ignored' }}
-        ${'args("foo", "bar", "baz")'}                               | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
-        ${'arrayOf("foo", "bar", "baz")'}                            | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
-        ${'listOf("foo", "bar", "baz")'}                             | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
-        ${'mutableListOf("foo", "bar", "baz")'}                      | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
-        ${'setOf("foo", "bar", "baz")'}                              | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
-        ${'mutableSetOf("foo", "bar", "baz")'}                       | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
-        ${'stages("foo", "bar", "baz")'}                             | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
-      `('$input', async ({ input, output }) => {
-        const { deps } = await parseGradle(input);
+        def                                  | str                           | output
+        ${'foo = "1.2.3"'}                   | ${'"foo:bar:$foo@@@"'}        | ${null}
+        ${''}                                | ${'"foo:bar:$baz"'}           | ${null}
+        ${'foo = "1"; bar = "2"; baz = "3"'} | ${'"foo:bar:$foo.$bar.$baz"'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', skipReason: 'contains-variable' }}
+        ${'baz = "1.2.3"'}                   | ${'"foo:bar:$baz"'}           | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
+        ${'foo.bar = "1.2.3"'}               | ${'"foo:bar:$foo.bar"'}       | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'foo.bar' }}
+        ${'foo = "1.2.3"'}                   | ${'"foo:bar_$foo:4.5.6"'}     | ${{ depName: 'foo:bar_1.2.3', managerData: { fileReplacePosition: 28 } }}
+        ${'baz = "1.2.3"'}                   | ${'foobar = "foo:bar:$baz"'}  | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
+      `('$def | $str', async ({ def, str, output }) => {
+        const { deps } = await parseGradle([def, str].join('\n'));
         expect(deps).toMatchObject([output].filter(Boolean));
       });
     });
 
-    describe('variable substitutions', () => {
+    describe('map notation dependencies', () => {
       test.each`
-        def                                           | str                                                     | output
-        ${'foo = "1.2.3"'}                            | ${'"foo:bar:$foo@@@"'}                                  | ${null}
-        ${'foo = "1"; bar = "2"; baz = "3"'}          | ${'"foo:bar:$foo.$bar.$baz"'}                           | ${{ depName: 'foo:bar', currentValue: '1.2.3', skipReason: 'contains-variable' }}
-        ${'baz = "1.2.3"'}                            | ${'"foo:bar:$baz"'}                                     | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
-        ${'foo.bar = "1.2.3"'}                        | ${'"foo:bar:$foo.bar"'}                                 | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'foo.bar' }}
-        ${'foo = "1.2.3"'}                            | ${'"foo:bar_$foo:4.5.6"'}                               | ${{ depName: 'foo:bar_1.2.3', managerData: { fileReplacePosition: 28 } }}
-        ${''}                                         | ${'foo.bar = "foo:bar:1.2.3"'}                          | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
-        ${'baz = "1.2.3"'}                            | ${'foobar = "foo:bar:$baz"'}                            | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
-        ${'baz = "1.2.3"'}                            | ${'group: "foo", name: "bar", version: baz'}            | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
-        ${'baz = "1.2.3"'}                            | ${'library("foo.bar", "foo", "bar").versionRef("baz")'} | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
-        ${''}                                         | ${'library("foo.bar", "foo", "bar").version("1.2.3")'}  | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
-        ${'library("foo-bar_baz-qux", "foo", "bar")'} | ${'"${foo.bar.baz.qux}:1.2.3"'}                         | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+        def                | str                                                                               | output
+        ${''}              | ${'group: "foo", name: "bar", version: "1.2.3"'}                                  | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+        ${''}              | ${'group: "foo", name: "bar", version: baz'}                                      | ${null}
+        ${'baz = "1.2.3"'} | ${'group: "foo", name: "bar", version: baz'}                                      | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
+        ${''}              | ${'(group: "foo", name: "bar", version: "1.2.3", classifier: "sources")'}         | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+        ${''}              | ${'(group: "foo", name: "bar", version: "1.2.3") {exclude module: "spring-jcl"}'} | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+        ${''}              | ${"implementation platform(group: 'foo', name: 'bar', version: '1.2.3')"}         | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+        ${''}              | ${'(group = "foo", name = "bar", version = "1.2.3")'}                             | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
       `('$def | $str', async ({ def, str, output }) => {
-        const input = [def, str].join('\n');
-        const { deps } = await parseGradle(input);
+        const { deps } = await parseGradle([def, str].join('\n'));
         expect(deps).toMatchObject([output].filter(Boolean));
       });
     });
 
     describe('plugins', () => {
       test.each`
-        def                 | input                               | output
-        ${''}               | ${'id "foo.bar" version "1.2.3"'}   | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
-        ${''}               | ${'id("foo.bar") version "1.2.3"'}  | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
-        ${''}               | ${'kotlin("jvm") version "1.3.71"'} | ${{ depName: 'org.jetbrains.kotlin.jvm', packageName: 'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin', currentValue: '1.3.71' }}
-        ${''}               | ${'id "foo.bar" version something'} | ${{ depName: 'foo.bar', currentValue: 'something', skipReason: 'unknown-version' }}
-        ${'baz = "1.2.3"'}  | ${'id "foo.bar" version baz'}       | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
-        ${'baz = "1.2.3"'}  | ${'id("foo.bar") version baz'}      | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
-        ${'baz = "1.3.71"'} | ${'kotlin("jvm") version baz'}      | ${{ depName: 'org.jetbrains.kotlin.jvm', packageName: 'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin', currentValue: '1.3.71' }}
-        ${'z = "1.2.3"'}    | ${'id "x.y" version "$z"'}          | ${{ depName: 'x.y', packageName: 'x.y:x.y.gradle.plugin', currentValue: '1.2.3' }}
-        ${''}               | ${'id "x.y" version "$z"'}          | ${{ depName: 'x.y', skipReason: 'unknown-version', currentValue: 'z' }}
-        ${''}               | ${'id "x.y" version "x${y}z"'}      | ${{ depName: 'x.y', skipReason: 'unknown-version' }}
-        ${'z = "1.2.3"'}    | ${'id("x.y") version "$z"'}         | ${{ depName: 'x.y', packageName: 'x.y:x.y.gradle.plugin', currentValue: '1.2.3' }}
-        ${''}               | ${'id("x.y") version "$z"'}         | ${{ depName: 'x.y', skipReason: 'unknown-version', currentValue: 'z' }}
-        ${''}               | ${'id("x.y") version "x${y}z"'}     | ${{ depName: 'x.y', skipReason: 'unknown-version' }}
-      `('$input', async ({ def, input, output }) => {
+        def                 | input                                 | output
+        ${''}               | ${'id "foo.bar" version "1.2.3"'}     | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
+        ${''}               | ${'id(["foo.bar"]) version "1.2.3"'}  | ${null}
+        ${''}               | ${'id("foo", "bar") version "1.2.3"'} | ${null}
+        ${''}               | ${'id("foo.bar") version "1.2.3"'}    | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
+        ${''}               | ${'id "foo.bar" version "$baz"'}      | ${{ depName: 'foo.bar', skipReason: 'unknown-version', currentValue: 'baz' }}
+        ${'baz = "1.2.3"'}  | ${'id "foo.bar" version "$baz"'}      | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
+        ${'baz = "1.2.3"'}  | ${'id("foo.bar") version "$baz"'}     | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
+        ${''}               | ${'id "foo.bar" version "x${ab}cd"'}  | ${{ depName: 'foo.bar', skipReason: 'unknown-version' }}
+        ${''}               | ${'id("foo.bar") version "$baz"'}     | ${{ depName: 'foo.bar', skipReason: 'unknown-version', currentValue: 'baz' }}
+        ${''}               | ${'id("foo.bar") version "x${ab}cd"'} | ${{ depName: 'foo.bar', skipReason: 'unknown-version' }}
+        ${''}               | ${'id "foo.bar" version baz'}         | ${{ depName: 'foo.bar', currentValue: 'baz', skipReason: 'unknown-version' }}
+        ${'baz = "1.2.3"'}  | ${'id "foo.bar" version baz'}         | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
+        ${'baz = "1.2.3"'}  | ${'id("foo.bar") version baz'}        | ${{ depName: 'foo.bar', packageName: 'foo.bar:foo.bar.gradle.plugin', currentValue: '1.2.3' }}
+        ${''}               | ${'kotlin("jvm") version "1.3.71"'}   | ${{ depName: 'org.jetbrains.kotlin.jvm', packageName: 'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin', currentValue: '1.3.71' }}
+        ${'baz = "1.3.71"'} | ${'kotlin("jvm") version baz'}        | ${{ depName: 'org.jetbrains.kotlin.jvm', packageName: 'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin', currentValue: '1.3.71' }}
+      `('$def | $input', async ({ def, input, output }) => {
         const { deps } = await parseGradle([def, input].join('\n'));
         expect(deps).toMatchObject([output].filter(Boolean));
       });
     });
   });
 
-  describe('registryUrls', () => {
+  describe('registries', () => {
+    describe('predefined registries', () => {
+      test.each`
+        input                                          | output
+        ${'mavenCentral()'}                            | ${MAVEN_REPO}
+        ${'google()'}                                  | ${GOOGLE_REPO}
+        ${'google { content { includeGroup "foo" } }'} | ${GOOGLE_REPO}
+        ${'gradlePluginPortal()'}                      | ${GRADLE_PLUGIN_PORTAL_REPO}
+        ${'jcenter()'}                                 | ${JCENTER_REPO}
+      `('$input', async ({ input, output }) => {
+        const { urls } = await parseGradle(input);
+        expect(urls).toStrictEqual([output].filter(Boolean));
+      });
+    });
+
+    describe('custom registries', () => {
+      test.each`
+        def                         | input                                                | url
+        ${''}                       | ${'maven("")'}                                       | ${null}
+        ${''}                       | ${'maven(["https://foo.bar/baz/qux"])'}              | ${null}
+        ${''}                       | ${'maven("foo", "bar")'}                             | ${null}
+        ${''}                       | ${'maven("https://foo.bar/baz")'}                    | ${'https://foo.bar/baz'}
+        ${'base="https://foo.bar"'} | ${'maven("${base}/baz")'}                            | ${'https://foo.bar/baz'}
+        ${''}                       | ${'maven(uri(["https://foo.bar/baz"]))'}             | ${null}
+        ${''}                       | ${'maven { ["https://foo.bar/baz"] }'}               | ${null}
+        ${''}                       | ${'maven { url "https://foo.bar/baz" }'}             | ${'https://foo.bar/baz'}
+        ${'base="https://foo.bar"'} | ${'maven { url "${base}/baz" }'}                     | ${'https://foo.bar/baz'}
+        ${''}                       | ${'maven { url = "https://foo.bar/baz" }'}           | ${'https://foo.bar/baz'}
+        ${'base="https://foo.bar"'} | ${'maven { url = "${base}/baz" }'}                   | ${'https://foo.bar/baz'}
+        ${''}                       | ${'maven { url = uri("https://foo.bar/baz") }'}      | ${'https://foo.bar/baz'}
+        ${'base="https://foo.bar"'} | ${'maven { url = uri("${base}/baz") }'}              | ${'https://foo.bar/baz'}
+        ${'base="https://foo.bar"'} | ${'maven { name = "baz"\nurl = "${base}/${name}" }'} | ${'https://foo.bar/baz'}
+      `('$def | $input', async ({ def, input, url }) => {
+        const expected = [url].filter(Boolean);
+        const { urls } = await parseGradle([def, input].join('\n'));
+        expect(urls).toStrictEqual(expected);
+      });
+    });
+  });
+
+  describe('version catalog', () => {
     test.each`
-      def                         | input                                              | url
-      ${''}                       | ${'url ""'}                                        | ${null}
-      ${''}                       | ${'url "#!@"'}                                     | ${null}
-      ${''}                       | ${'url "https://example.com"'}                     | ${'https://example.com'}
-      ${'base="https://foo.bar"'} | ${'url "${base}/baz"'}                             | ${'https://foo.bar/baz'}
-      ${''}                       | ${'url("https://example.com")'}                    | ${'https://example.com'}
-      ${'base="https://foo.bar"'} | ${'url("${base}/baz")'}                            | ${'https://foo.bar/baz'}
-      ${''}                       | ${'mavenCentral()'}                                | ${MAVEN_REPO}
-      ${''}                       | ${'jcenter()'}                                     | ${JCENTER_REPO}
-      ${''}                       | ${'google()'}                                      | ${GOOGLE_REPO}
-      ${''}                       | ${'google { content { includeGroup "foo" } }'}     | ${GOOGLE_REPO}
-      ${''}                       | ${'gradlePluginPortal()'}                          | ${GRADLE_PLUGIN_PORTAL_REPO}
-      ${''}                       | ${'maven("https://foo.bar/baz/qux")'}              | ${'https://foo.bar/baz/qux'}
-      ${'base="https://foo.bar"'} | ${'maven("${base}/baz/qux")'}                      | ${'https://foo.bar/baz/qux'}
-      ${''}                       | ${'maven { url = uri("https://foo.bar/baz")'}      | ${'https://foo.bar/baz'}
-      ${'base="https://foo.bar"'} | ${'maven { url = uri("${base}/baz")'}              | ${'https://foo.bar/baz'}
-      ${''}                       | ${"maven { url 'https://foo.bar/baz'"}             | ${'https://foo.bar/baz'}
-      ${'base="https://foo.bar"'} | ${'maven { url "${base}/baz"'}                     | ${'https://foo.bar/baz'}
-      ${''}                       | ${"maven { url = 'https://foo.bar/baz'"}           | ${'https://foo.bar/baz'}
-      ${'base="https://foo.bar"'} | ${'maven { url = "${base}/baz"'}                   | ${'https://foo.bar/baz'}
-      ${'base="https://foo.bar"'} | ${'maven { name = "baz"\nurl = "${base}/${name}"'} | ${'https://foo.bar/baz'}
-    `('$def | $input', async ({ def, input, url }) => {
-      const expected = [url].filter(Boolean);
-      const { urls } = await parseGradle([def, input].join('\n'));
-      expect(urls).toStrictEqual(expected);
+      def                                           | str                                                             | output
+      ${'version("baz", "1.2.3")'}                  | ${'library("foo.bar", "foo", "bar").versionRef("baz")'}         | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
+      ${'version("baz", "1.2.3")'}                  | ${'library("foo.bar", "foo", "bar").versionRef("baz")'}         | ${{ depName: 'foo:bar', currentValue: '1.2.3', groupName: 'baz' }}
+      ${''}                                         | ${'library("foo.bar", "foo", "bar").version("1.2.3")'}          | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+      ${''}                                         | ${'library(["foo.bar", "foo", "bar"]).version("1.2.3")'}        | ${null}
+      ${''}                                         | ${'library("foo", "bar", "baz", "qux"]).version("1.2.3")'}      | ${null}
+      ${''}                                         | ${'library("foo.bar", "foo", "bar").version("1.2.3", "4.5.6")'} | ${null}
+      ${'group = "foo"; artifact="bar"'}            | ${'library("foo.bar", group, artifact).version("1.2.3")'}       | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+      ${'library("foo-bar_baz-qux", "foo", "bar")'} | ${'"${foo.bar.baz.qux}:1.2.3"'}                                 | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+    `('$def | $str', async ({ def, str, output }) => {
+      const input = [def, str].join('\n');
+      const { deps } = await parseGradle(input);
+      expect(deps).toMatchObject([output].filter(Boolean));
+    });
+  });
+
+  describe('heuristic dependency matching', () => {
+    test.each`
+      input                                                        | output
+      ${'("foo", "bar", "1.2.3")'}                                 | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+      ${'("foo", "bar", "1.2.3", "4.5.6")'}                        | ${null}
+      ${'(["foo", "bar", "1.2.3"])'}                               | ${null}
+      ${'someMethod("foo", "bar", "1.2.3")'}                       | ${{ depName: 'foo:bar', currentValue: '1.2.3' }}
+      ${'createXmlValueRemover("defaults", "integer", "integer")'} | ${{ depName: 'defaults:integer', currentValue: 'integer', skipReason: 'ignored' }}
+      ${'events("passed", "skipped", "failed")'}                   | ${{ depName: 'passed:skipped', currentValue: 'failed', skipReason: 'ignored' }}
+      ${'args("foo", "bar", "baz")'}                               | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
+      ${'arrayOf("foo", "bar", "baz")'}                            | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
+      ${'listOf("foo", "bar", "baz")'}                             | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
+      ${'mutableListOf("foo", "bar", "baz")'}                      | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
+      ${'setOf("foo", "bar", "baz")'}                              | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
+      ${'mutableSetOf("foo", "bar", "baz")'}                       | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
+      ${'stages("foo", "bar", "baz")'}                             | ${{ depName: 'foo:bar', currentValue: 'baz', skipReason: 'ignored' }}
+    `('$input', async ({ input, output }) => {
+      const { deps } = await parseGradle(input);
+      expect(deps).toMatchObject([output].filter(Boolean));
     });
   });
 
@@ -241,34 +296,39 @@ describe('modules/manager/gradle/parser', () => {
       },
     };
 
-    mockFs({
+    const fileContents = {
       'foo/bar.gradle': key + ' = "' + value + '"',
-    });
+    };
+    mockFs(fileContents);
 
     test.each`
-      def             | input                                               | output
-      ${''}           | ${'apply from: ""'}                                 | ${{}}
-      ${''}           | ${'apply from: "foo/invalid.gradle"'}               | ${{}}
-      ${''}           | ${'apply from: "foo/invalid.non-gradle"'}           | ${{}}
-      ${''}           | ${'apply from: "https://someurl.com/file.gradle"'}  | ${{}}
-      ${''}           | ${'apply from: "foo/bar.gradle"'}                   | ${validOutput}
-      ${'base="foo"'} | ${'apply from: "${base}/bar.gradle"'}               | ${validOutput}
-      ${''}           | ${'apply from: file("foo/bar.gradle")'}             | ${validOutput}
-      ${'base="foo"'} | ${'apply from: file("${base}/bar.gradle")'}         | ${validOutput}
-      ${''}           | ${'apply from: project.file("foo/bar.gradle")'}     | ${validOutput}
-      ${''}           | ${'apply from: rootProject.file("foo/bar.gradle")'} | ${validOutput}
-      ${''}           | ${'apply from: new File("foo/bar.gradle")'}         | ${validOutput}
-      ${'base="foo"'} | ${'apply from: new File("${base}/bar.gradle")'}     | ${validOutput}
-      ${''}           | ${'apply from: new File("foo", "bar.gradle")'}      | ${validOutput}
-      ${'base="foo"'} | ${'apply from: new File(base, "bar.gradle")'}       | ${validOutput}
-      ${'base="foo"'} | ${'apply from: new File("${base}", "bar.gradle")'}  | ${validOutput}
-      ${''}           | ${'apply(from = "foo/bar.gradle"))'}                | ${validOutput}
-      ${'base="foo"'} | ${'apply(from = "${base}/bar.gradle"))'}            | ${validOutput}
-      ${''}           | ${'apply(from = File("foo/bar.gradle"))'}           | ${validOutput}
-      ${'base="foo"'} | ${'apply(from = File("${base}/bar.gradle"))'}       | ${validOutput}
-      ${''}           | ${'apply(from = File("foo", "bar.gradle"))'}        | ${validOutput}
-      ${'base="foo"'} | ${'apply(from = File(base, "bar.gradle"))'}         | ${validOutput}
-      ${'base="foo"'} | ${'apply(from = File("${base}", "bar.gradle"))'}    | ${validOutput}
+      def                    | input                                               | output
+      ${''}                  | ${'apply from: ""'}                                 | ${{}}
+      ${''}                  | ${'apply from: "foo/invalid.gradle"'}               | ${{}}
+      ${''}                  | ${'apply from: "${base}"'}                          | ${{}}
+      ${''}                  | ${'apply from: "foo/invalid.non-gradle"'}           | ${{}}
+      ${''}                  | ${'apply from: "https://someurl.com/file.gradle"'}  | ${{}}
+      ${''}                  | ${'apply from: "foo/bar.gradle"'}                   | ${validOutput}
+      ${'base="foo"'}        | ${'apply from: "${base}/bar.gradle"'}               | ${validOutput}
+      ${''}                  | ${'apply from: file("foo/bar.gradle")'}             | ${validOutput}
+      ${'base="foo"'}        | ${'apply from: file("${base}/bar.gradle")'}         | ${validOutput}
+      ${''}                  | ${'apply from: project.file("foo/bar.gradle")'}     | ${validOutput}
+      ${''}                  | ${'apply from: rootProject.file("foo/bar.gradle")'} | ${validOutput}
+      ${''}                  | ${'apply from: new File("foo/bar.gradle")'}         | ${validOutput}
+      ${'base="foo"'}        | ${'apply from: new File("${base}/bar.gradle")'}     | ${validOutput}
+      ${''}                  | ${'apply from: new File("foo", "bar.gradle")'}      | ${validOutput}
+      ${'base="foo"'}        | ${'apply from: new File(base, "bar.gradle")'}       | ${validOutput}
+      ${'base="foo"'}        | ${'apply from: new File("${base}", "bar.gradle")'}  | ${validOutput}
+      ${'path="bar.gradle"'} | ${'apply from: new File("foo", "${path}")'}         | ${validOutput}
+      ${''}                  | ${'apply(from = "foo/bar.gradle"))'}                | ${validOutput}
+      ${'base="foo"'}        | ${'apply(from = "${base}/bar.gradle"))'}            | ${validOutput}
+      ${''}                  | ${'apply(from = File("foo/bar.gradle"))'}           | ${validOutput}
+      ${''}                  | ${'apply(from = File("foo", "bar", "baz"))'}        | ${{}}
+      ${''}                  | ${'apply(from = File(["${somedir}/foo.gradle"]))'}  | ${{}}
+      ${'base="foo"'}        | ${'apply(from = File("${base}/bar.gradle"))'}       | ${validOutput}
+      ${''}                  | ${'apply(from = File("foo", "bar.gradle"))'}        | ${validOutput}
+      ${'base="foo"'}        | ${'apply(from = File(base, "bar.gradle"))'}         | ${validOutput}
+      ${'base="foo"'}        | ${'apply(from = File("${base}", "bar.gradle"))'}    | ${validOutput}
     `('$def | $input', async ({ def, input, output }) => {
       const { vars } = await parseGradle([def, input].join('\n'));
       expect(vars).toMatchObject(output);