Skip to content

Reduce function nesting depth to meet SonarQube standards#4286

Open
sonarqube-agent[bot] wants to merge 1 commit into
mainfrom
remediate-main-20260609-090142-a757f5bb
Open

Reduce function nesting depth to meet SonarQube standards#4286
sonarqube-agent[bot] wants to merge 1 commit into
mainfrom
remediate-main-20260609-090142-a757f5bb

Conversation

@sonarqube-agent

Copy link
Copy Markdown

This PR was automatically created by the Remediation Agent's Scheduled backlog remediation feature.

Why these issues? All five fixed issues are CRITICAL severity S2004 violations in production source code that share a common pattern of excessive function nesting. These violations represent genuine code quality improvements with high success rates for automated fixes, making them ideal candidates for a focused refactoring effort.

This PR refactors five instances of deeply nested functions across multiple files to comply with SonarQube's 4-level nesting limit. By extracting nested callbacks and inner functions into standalone helper functions at the module or component level, the code becomes more maintainable and eliminates critical code smells that indicate potential cognitive complexity issues.

View Project in SonarCloud


Fixed Issues

typescript:S2004 - Refactor this code to not nest functions more than 4 levels deep. • CRITICALView issue

Location: src/node-lib/educator-api/helpers/saveUnits/useMyLibrary.tsx:142

Why is this an issue?

Nested functions refer to the practice of defining a function within another function. These inner functions have access to the variables and parameters of the outer function, creating a closure.

What changed

Extracts the deeply nested inline error handler functions into standalone helper functions (handleSaveError and handleUnsaveError) at a lower nesting level. This reduces the function nesting depth that was previously exceeding the 4-level limit. The filter callback (slug) => slug !== unitProgrammeSlug that was at nesting level 5 inside the inline anonymous function is now only at nesting level 3 (useMyLibrary -> handleSaveError -> setLocallySavedUnits callback -> filter callback), which is within the allowed threshold.

--- a/src/node-lib/educator-api/helpers/saveUnits/useMyLibrary.tsx
+++ b/src/node-lib/educator-api/helpers/saveUnits/useMyLibrary.tsx
@@ -125,0 +126,16 @@ export const useMyLibrary = () => {
+  const handleSaveError = (unitProgrammeSlug: string) => {
+    // Revert the optimistic update if the request fails and show an error toast
+    setCurrentToastProps(ErrorToastProps);
+    setLocallySavedUnits((prev) =>
+      prev.filter((slug) => slug !== unitProgrammeSlug),
+    );
+    decrementSavedUnitsCount();
+  };
+
+  const handleUnsaveError = (unitProgrammeSlug: string) => {
+    // Revert the optimistic update if the request fails and show an error toast
+    setCurrentToastProps(ErrorToastProps);
+    setLocallySavedUnits((prev) => [...prev, unitProgrammeSlug]);
+    incrementSavedUnitsCount();
+  };
+
typescript:S2004 - Refactor this code to not nest functions more than 4 levels deep. • CRITICALView issue

Location: src/node-lib/educator-api/helpers/saveUnits/useSaveUnits.tsx:90

Why is this an issue?

Nested functions refer to the practice of defining a function within another function. These inner functions have access to the variables and parameters of the outer function, creating a closure.

What changed

Extracts the deeply nested inline error-handling callbacks into named helper functions (handleSaveError and handleUnsaveError) at a shallower nesting level. This reduces the function nesting depth so that the inner arrow functions (like prev.filter((unit) => unit !== unitSlug)) no longer exceed the 4-level nesting threshold, directly addressing the code smell about nesting functions more than 4 levels deep.

--- a/src/node-lib/educator-api/helpers/saveUnits/useSaveUnits.tsx
+++ b/src/node-lib/educator-api/helpers/saveUnits/useSaveUnits.tsx
@@ -79,0 +80,16 @@ export const useSaveUnits = (
+  const handleSaveError = (unitSlug: string) => {
+    // Revert the optimistic update if the request fails and show an error toast
+    setLocallySavedUnits((prev) =>
+      prev.filter((unit) => unit !== unitSlug),
+    );
+    setCurrentToastProps(ErrorToastProps);
+    decrementSavedUnitsCount();
+  };
+
+  const handleUnsaveError = (unitSlug: string) => {
+    // Revert the optimistic update if the request fails and show an error toast
+    setLocallySavedUnits((prev) => [...prev, unitSlug]);
+    setCurrentToastProps(ErrorToastProps);
+    incrementSavedUnitsCount();
+  };
+
typescript:S2004 - Refactor this code to not nest functions more than 4 levels deep. • CRITICALView issue

Location: src/pages-helpers/curriculum/docx/builder/10_threadsDetail.ts:137

Why is this an issue?

Nested functions refer to the practice of defining a function within another function. These inner functions have access to the variables and parameters of the outer function, creating a closure.

What changed

Defines a new top-level helper function filterUnitsByThread that extracts the previously nested function out of the generate function. This reduces the nesting depth of the inner lambda functions (the .filter and .findIndex callbacks) by moving them from being nested 4+ levels deep inside generate to being only 2 levels deep inside this standalone function, directly addressing the code smell about nesting functions more than 4 levels deep.

--- a/src/pages-helpers/curriculum/docx/builder/10_threadsDetail.ts
+++ b/src/pages-helpers/curriculum/docx/builder/10_threadsDetail.ts
@@ -59,0 +60,6 @@ function renderUnits(units: Unit[], numbering: { unitNumbering: string }) {
+function filterUnitsByThread(units: Unit[], threadSlug: string): Unit[] {
+  return units.filter(
+    (u) => u.threads.findIndex((t) => t.slug === threadSlug) > -1,
+  );
+}
+
typescript:S2004 - Refactor this code to not nest functions more than 4 levels deep. • CRITICALView issue

Location: src/node-lib/curriculum-api-2023/queries/unitListing/helpers/getAllCategories.ts:66

Why is this an issue?

Nested functions refer to the practice of defining a function within another function. These inner functions have access to the variables and parameters of the outer function, creating a closure.

What changed

Extracts the deeply nested logic into a standalone top-level helper function applySlugToUnit. This reduces the nesting depth inside applySlugsToUnitCategories by moving the inner function body (which contained nested arrow functions for .map() and .find()) out to the module level, thereby eliminating the excessive function nesting that exceeded the 4-level threshold.

--- a/src/node-lib/curriculum-api-2023/queries/unitListing/helpers/getAllCategories.ts
+++ b/src/node-lib/curriculum-api-2023/queries/unitListing/helpers/getAllCategories.ts
@@ -56,0 +57,14 @@ export const getAllCategories = (
+const applySlugToUnit = (
+  categories: SubjectCategory[],
+  unit: GroupedUnitsSchema[number][number],
+) => {
+  const newUnit = { ...unit };
+  if (newUnit.subjectCategories) {
+    newUnit.subjectCategories = newUnit.subjectCategories.map((sc) => {
+      const category = categories.find((c) => c.label === sc.label);
+      return { ...sc, slug: category?.slug };
+    });
+  }
+  return newUnit;
+};
+
typescript:S2004 - Refactor this code to not nest functions more than 4 levels deep. • CRITICALView issue

Location: src/components/TeacherViews/LessonOverview/hasLessonMathJax.ts:39

Why is this an issue?

Nested functions refer to the practice of defining a function within another function. These inner functions have access to the variables and parameters of the outer function, creating a closure.

What changed

Extracts the deeply nested findMatch function to the module level as findMatchingMathJax. This reduces the nesting depth of functions inside hasQuizMathJax, directly addressing the code smell about nesting functions more than 4 levels deep. The arrow function (a) => a.type === "text" that was previously at nesting level 5 is now at a much shallower level since the function is defined at the top level of the module.

--- a/src/components/TeacherViews/LessonOverview/hasLessonMathJax.ts
+++ b/src/components/TeacherViews/LessonOverview/hasLessonMathJax.ts
@@ -22,0 +23,7 @@ export const containsMathJax = (text: string | undefined | null): boolean => {
+const findMatchingMathJax = (answer: StemObject[]) => {
+  if (!answer) return false;
+  return answer.some(
+    (a) => a.type === "text" && containsMathJax(a.text),
+  );
+};
+

Have a suggestion or found an issue? Share your feedback here.


SonarQube Remediation Agent uses AI. Check for mistakes.

Fixed issues:
- AZObcE-7vuTsgZ3mrklt for typescript:S2004 rule
- AZbPCi1lp-jr4SR56zmn for typescript:S2004 rule
- AZTbbOa0QYLNS-EXxw7B for typescript:S2004 rule
- AZcv7V9QlBqAYD-b54hx for typescript:S2004 rule
- AY7ww-qPBNT4s_jVn-2A for typescript:S2004 rule

Generated by SonarQube Agent (task: 0574019f-2d09-4dbd-b45e-9d1e2db16c78)
@vercel

vercel Bot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
oak-web-application-storybook Ready Ready Preview, Comment Jun 9, 2026 9:11am
oak-web-application-website Ready Ready Preview, Comment Jun 9, 2026 9:11am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant