From 0e7c4306ec00f2701b7427f9954e5df3583066df Mon Sep 17 00:00:00 2001
From: Hasan Awad <90554456+hasanwhitesource@users.noreply.github.com>
Date: Tue, 9 Aug 2022 22:51:43 +0300
Subject: [PATCH] refactor(manager/go): make multiline parsing a function
 (#17074)

* make multiline parsing a function

* refactor

* added interface for type

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
---
 lib/modules/manager/gomod/extract.ts | 52 ++++++++++++++++++++--------
 lib/modules/manager/gomod/types.ts   |  6 ++++
 2 files changed, 43 insertions(+), 15 deletions(-)
 create mode 100644 lib/modules/manager/gomod/types.ts

diff --git a/lib/modules/manager/gomod/extract.ts b/lib/modules/manager/gomod/extract.ts
index 935f63e4c2..61d30af520 100644
--- a/lib/modules/manager/gomod/extract.ts
+++ b/lib/modules/manager/gomod/extract.ts
@@ -5,6 +5,7 @@ import { GoDatasource } from '../../datasource/go';
 import { GolangVersionDatasource } from '../../datasource/golang-version';
 import { isVersion } from '../../versioning/semver';
 import type { PackageDependency, PackageFile } from '../types';
+import type { MultiLineParseResult } from './types';
 
 function getDep(
   lineNumber: number,
@@ -56,7 +57,7 @@ export function extractPackageFile(content: string): PackageFile | null {
   try {
     const lines = content.split(newlineRegex);
     for (let lineNumber = 0; lineNumber < lines.length; lineNumber += 1) {
-      let line = lines[lineNumber];
+      const line = lines[lineNumber];
       const goVer = line.startsWith('go ') ? line.replace('go ', '') : null;
       if (goVer && semver.validRange(goVer)) {
         const dep = getGoDep(lineNumber, goVer);
@@ -78,20 +79,15 @@ export function extractPackageFile(content: string): PackageFile | null {
       }
       if (line.trim() === 'require (') {
         logger.trace(`Matched multi-line require on line ${lineNumber}`);
-        do {
-          lineNumber += 1;
-          line = lines[lineNumber];
-          const multiMatch = regEx(/^\s+([^\s]+)\s+([^\s]+)/).exec(line);
-          logger.trace(`reqLine: "${line}"`);
-          if (multiMatch && !line.endsWith('// indirect')) {
-            logger.trace({ lineNumber }, `require line: "${line}"`);
-            const dep = getDep(lineNumber, multiMatch, 'require');
-            dep.managerData!.multiLine = true;
-            deps.push(dep);
-          } else if (line.trim() !== ')') {
-            logger.trace(`No multi-line match: ${line}`);
-          }
-        } while (line.trim() !== ')');
+        const matcher = regEx(/^\s+([^\s]+)\s+([^\s]+)/);
+        const { reachedLine, detectedDeps } = parseMultiLine(
+          lineNumber,
+          lines,
+          matcher,
+          'require'
+        );
+        lineNumber = reachedLine;
+        deps.push(...detectedDeps);
       }
     }
   } catch (err) /* istanbul ignore next */ {
@@ -102,3 +98,29 @@ export function extractPackageFile(content: string): PackageFile | null {
   }
   return { constraints, deps };
 }
+
+function parseMultiLine(
+  startingLine: number,
+  lines: string[],
+  matchRegex: RegExp,
+  blockType: 'require' | 'replace'
+): MultiLineParseResult {
+  const deps: PackageDependency[] = [];
+  let lineNumber = startingLine;
+  let line = '';
+  do {
+    lineNumber += 1;
+    line = lines[lineNumber];
+    const multiMatch = matchRegex.exec(line);
+    logger.trace(`${blockType}: "${line}"`);
+    if (multiMatch && !line.endsWith('// indirect')) {
+      logger.trace({ lineNumber }, `${blockType} line: "${line}"`);
+      const dep = getDep(lineNumber, multiMatch, blockType);
+      dep.managerData!.multiLine = true;
+      deps.push(dep);
+    } else if (line.trim() !== ')') {
+      logger.trace(`No multi-line match: ${line}`);
+    }
+  } while (line.trim() !== ')');
+  return { reachedLine: lineNumber, detectedDeps: deps };
+}
diff --git a/lib/modules/manager/gomod/types.ts b/lib/modules/manager/gomod/types.ts
new file mode 100644
index 0000000000..70c3dace8b
--- /dev/null
+++ b/lib/modules/manager/gomod/types.ts
@@ -0,0 +1,6 @@
+import type { PackageDependency } from '../types';
+
+export interface MultiLineParseResult {
+  reachedLine: number;
+  detectedDeps: PackageDependency[];
+}
-- 
GitLab