Skip to content

test: lift new-code coverage on Disassembler, GrobValue, GrobStruct, …#41

Merged
kwakker35 merged 7 commits into
mainfrom
feat/vm-dispatch-loop
May 26, 2026
Merged

test: lift new-code coverage on Disassembler, GrobValue, GrobStruct, …#41
kwakker35 merged 7 commits into
mainfrom
feat/vm-dispatch-loop

Conversation

@kwakker35

@kwakker35 kwakker35 commented May 25, 2026

Copy link
Copy Markdown
Collaborator

…GrobFunction

Sonar new-code coverage was 64.2%, below the 80% gate.

Disassembler: data-driven theory covers every OpCode dispatch arm, asserting the dispatch returns the documented instruction width and emits the opcode name. Width table mirrors the production dispatch so any future width drift fails loudly here.

GrobValue: per-kind Equals/GetHashCode tests for Map and Function reference paths, +0.0/-0.0 hash agreement, full strict and try-accessor matrices, and ArgumentNullException tests for the five reference-typed From* factories.

GrobStruct: null/empty TypeName guards, null field-name guards on GetField/SetField/TryGetField, missing-key behaviour, reflexive Equals and field-equality coverage.

GrobFunction: null name, negative arity, and empty-name-allowed contract.

Summary by CodeRabbit

  • New Features

    • Added a bytecode virtual machine with integer/float ops, string concatenation, print output and debug tracing.
    • New fixed‑capacity operand stack with overflow/underflow checks, snapshot/reset behaviour and GC‑safe clearing.
    • Runtime exceptions now include error code, source line and column for richer error reporting.
    • Chunk metadata now tracks per‑byte source columns and supports column‑aware writes.
  • Tests

    • Extensive tests covering VM execution, arithmetic errors (with codes/locations), stack behaviour, printing, column tracking and debug trace output.

Review Change Stack

…GrobFunction

Sonar new-code coverage was 64.2%, below the 80% gate.

Disassembler: data-driven theory covers every OpCode dispatch arm, asserting the dispatch returns the documented instruction width and emits the opcode name. Width table mirrors the production dispatch so any future width drift fails loudly here.

GrobValue: per-kind Equals/GetHashCode tests for Map and Function reference paths, +0.0/-0.0 hash agreement, full strict and try-accessor matrices, and ArgumentNullException tests for the five reference-typed From* factories.

GrobStruct: null/empty TypeName guards, null field-name guards on GetField/SetField/TryGetField, missing-key behaviour, reflexive Equals and field-equality coverage.

GrobFunction: null name, negative arity, and empty-name-allowed contract.
@kwakker35 kwakker35 self-assigned this May 25, 2026
@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds per-byte source column tracking and runtime exception types, implements a fixed-capacity ValueStack, implements a sealed VirtualMachine dispatch loop (arithmetic, constants, Print, error mapping and DEBUG tracing), and adds comprehensive VM and Chunk tests.

Changes

Bytecode VM Engine

Layer / File(s) Summary
Runtime exception hierarchy
src/Grob.Core/GrobRuntimeException.cs, src/Grob.Core/GrobArithmeticException.cs
GrobRuntimeException with Code, Line, Column and constructors; GrobArithmeticException adds a column-aware constructor.
Chunk column tracking
src/Grob.Core/Chunk.cs
Adds parallel _columns storage, GetColumn(int), and column-aware WriteByte/WriteOpCode overloads; existing overloads delegate with column=0.
Operand stack implementation
src/Grob.Vm/ValueStack.cs
Fixed-capacity ValueStack backed by GrobValue[] with Push(value,line) (overflow -> GrobRuntimeException E5903), Pop(), Peek(distance), Reset(), and AsSpan() for tracing.
Virtual machine execution engine
src/Grob.Vm/VirtualMachine.cs
Sealed VirtualMachine(TextWriter output, TextWriter? trace = null) and Run(Chunk): resets stack, fetch/decode/execute loop tracking line/column, supports constants (short/long), Nil/True/False, Pop/PopN, integer/float arithmetic mapped to GrobArithmeticException codes (E5001E5005), string concat, int->float promotion, Print to provided output, Return termination, malformed-chunk detection, and DEBUG-only per-instruction tracing.
Chunk column tests
tests/Grob.Core.Tests/ChunkColumnTests.cs
Two Xunit facts validating default column=0 semantics and explicit (line,column) round-trip.
VM acceptance and unit tests
tests/Grob.Vm.Tests/VirtualMachineTests.cs
Extensive tests exercising arithmetic, negation, promotion, concat, Print formatting, arithmetic error codes and line/column propagation, VM halt-on-first-error, ValueStack overflow and push/peek/pop round-trip, malformed-chunk detection, ConstantLong big-endian indexing, singleton literals, Pop/PopN, and DEBUG trace assertions.

Sequence Diagram

sequenceDiagram
  participant Caller
  participant VirtualMachine
  participant ValueStack
  participant Output
  Caller->>VirtualMachine: Run(Chunk)
  loop Each instruction
    VirtualMachine->>VirtualMachine: Fetch opcode, line, column
    alt Constant/Push
      VirtualMachine->>ValueStack: Push(...)
    else Arithmetic
      VirtualMachine->>ValueStack: Pop operands
      VirtualMachine->>VirtualMachine: Execute checked arithmetic (map to E5001–E5005)
      VirtualMachine->>ValueStack: Push result
    else Print
      VirtualMachine->>ValueStack: Peek top
      VirtualMachine->>Output: Write formatted value
    end
  end
  VirtualMachine->>Caller: Return or throw runtime/internal exception
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • grob-lang/grob#40: Earlier changes to src/Grob.Core/Chunk.cs that introduced the original line-aware write APIs; this PR extends the same class with per-byte column tracking.

Poem

A small VM wakes, opcodes in hand,
Checked maths and lines it understands,
Push and Pop keep stack in tune,
Errors carry codes and column noon,
Tests applaud as bytecode meets the moon.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title correctly uses the 'test:' Conventional Commits prefix as required, but the changeset describes VM implementation (GrobRuntimeException, ValueStack, VirtualMachine, Chunk column tracking) with comprehensive test coverage, making the title misleading about the primary scope of changes. Revise the title to accurately reflect the main changes. Consider 'feat(vm): implement stack-based VM dispatch loop with runtime exceptions and column tracking' or similar, keeping test coverage descriptions in the PR body.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 63.04% which is sufficient. The required threshold is 10.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/vm-dispatch-loop

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread src/Grob.Vm/VirtualMachine.cs Fixed
Comment thread src/Grob.Vm/VirtualMachine.cs Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
tests/Grob.Vm.Tests/VirtualMachineTests.cs (2)

1-3: ⚡ Quick win

Reorder using directives to match repository convention.

Xunit should come before Grob.Core (System.*, external, then Grob.*).

Proposed fix
 using System.Text;
-using Grob.Core;
 using Xunit;
+using Grob.Core;

As per coding guidelines "Order using directives as: System.* first, then external packages, then Grob.*, followed by a blank line, then file-scoped namespace declaration".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Grob.Vm.Tests/VirtualMachineTests.cs` around lines 1 - 3, Reorder the
using directives at the top of VirtualMachineTests.cs so they follow the repo
convention: System.* first (e.g., System.Text), then external packages (e.g.,
Xunit), then project namespaces (e.g., Grob.Core); ensure a blank line follows
the using block before the file-scoped namespace declaration (if present).
Locate the using lines containing System.Text, Grob.Core, and Xunit and reorder
them accordingly and add the blank line after the grouped usings.

83-83: ⚡ Quick win

Normalise test method names to a single underscore shape.

Several methods use more than one underscore. The test naming contract here is two PascalCase segments joined by exactly one underscore.

As per coding guidelines "Test method names must use the shape Subject_BehaviourClause — two PascalCase segments joined by a single underscore".

Also applies to: 122-122, 191-191, 208-208, 223-223, 343-343, 355-355, 467-467

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Grob.Vm.Tests/VirtualMachineTests.cs` at line 83, The test method names
use multiple underscores; rename them to the required Subject_BehaviourClause
form with exactly one underscore and two PascalCase segments: rename
IntArithmetic_BinaryOps_ProduceExpectedResult to
IntArithmetic_BinaryOpsProduceExpectedResult (i.e., Subject = IntArithmetic,
Behaviour = BinaryOpsProduceExpectedResult) and apply the same transformation to
the other test methods referenced (those with multiple underscores) so each
becomes OneSubjectSegment_OnePascalCaseBehaviourSegment; update all
references/usages accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Grob.Core/GrobRuntimeException.cs`:
- Around line 33-41: Move the public sealed class GrobArithmeticException out of
the file containing GrobRuntimeException and into its own file named
GrobArithmeticException.cs; keep the same namespace, XML doc comment,
constructor signature (public GrobArithmeticException(string code, int line,
string message) : base(code, line, message) { }), and accessibility, delete the
original type from the GrobRuntimeException file, and ensure the new file
compiles (add any required usings and update the project if necessary).

In `@src/Grob.Vm/ValueStack.cs`:
- Around line 55-59: The Peek method currently computes index = _top - 1 -
distance without validating distance, so a negative distance can produce an
out-of-range index; add an explicit guard at the start of ValueStack.Peek to
throw a GrobInternalException when distance < 0 (or otherwise reject negative
distances) before computing index, keeping the existing underflow check for
index < 0 and referencing _top and _values in the error handling to avoid raw
IndexOutOfRangeException.

In `@src/Grob.Vm/VirtualMachine.cs`:
- Around line 69-77: The opcode cases in VirtualMachine (cases OpCode.Constant,
OpCode.ConstantLong and the other multi-byte operand cases) currently call
Chunk.ReadByte(ip/ ip+1) without verifying remaining bytes; add explicit bounds
checks against the chunk's remaining byte count (using chunk.Count or similar)
before fetching operands and update ip only after validation, and if
insufficient bytes throw a VM-level internal error (not
ArgumentOutOfRangeException) so the VM reports a controlled error; specifically
guard reads in the Constant, ConstantLong (and the case around lines 85–87)
paths that use Chunk.ReadByte and Chunk.ReadConstant.
- Around line 46-50: Run currently leaves the VM's instance operand stack
(_stack) intact between invocations, which can leak values when reusing
VirtualMachine; at the start of the Run(Chunk chunk) method clear or
reinitialize the operand stack (e.g., call _stack.Clear() or assign a new stack)
and also reset any stack pointer/stackTop fields used by the VM so the VM starts
with an empty operand stack for each chunk.

In `@tests/Grob.Vm.Tests/VirtualMachineTests.cs`:
- Around line 240-252: The test IntModuloByZero_ThrowsE5003 only asserts
ex.Code; update it (and the other arithmetic error tests at the referenced
ranges) to assert the full diagnostic contract by also asserting ex.Line and
ex.Column (use the 1-based positions passed into Chunk.WriteOpCode in this test
— e.g. Assert.Equal(1, ex.Line) and Assert.Equal(1, ex.Column)); locate the
checks around GrobArithmeticException (the Assert.Throws call that invokes
vm.Run(chunk)) and add these two assertions immediately after verifying ex.Code.

---

Nitpick comments:
In `@tests/Grob.Vm.Tests/VirtualMachineTests.cs`:
- Around line 1-3: Reorder the using directives at the top of
VirtualMachineTests.cs so they follow the repo convention: System.* first (e.g.,
System.Text), then external packages (e.g., Xunit), then project namespaces
(e.g., Grob.Core); ensure a blank line follows the using block before the
file-scoped namespace declaration (if present). Locate the using lines
containing System.Text, Grob.Core, and Xunit and reorder them accordingly and
add the blank line after the grouped usings.
- Line 83: The test method names use multiple underscores; rename them to the
required Subject_BehaviourClause form with exactly one underscore and two
PascalCase segments: rename IntArithmetic_BinaryOps_ProduceExpectedResult to
IntArithmetic_BinaryOpsProduceExpectedResult (i.e., Subject = IntArithmetic,
Behaviour = BinaryOpsProduceExpectedResult) and apply the same transformation to
the other test methods referenced (those with multiple underscores) so each
becomes OneSubjectSegment_OnePascalCaseBehaviourSegment; update all
references/usages accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f3f71ec-b793-4c82-ac22-a4abc711447b

📥 Commits

Reviewing files that changed from the base of the PR and between 0c70b03 and 0b780a9.

📒 Files selected for processing (4)
  • src/Grob.Core/GrobRuntimeException.cs
  • src/Grob.Vm/ValueStack.cs
  • src/Grob.Vm/VirtualMachine.cs
  • tests/Grob.Vm.Tests/VirtualMachineTests.cs

Comment thread src/Grob.Core/GrobRuntimeException.cs Outdated
Comment thread src/Grob.Vm/ValueStack.cs
Comment thread src/Grob.Vm/VirtualMachine.cs
Comment thread src/Grob.Vm/VirtualMachine.cs
Comment thread tests/Grob.Vm.Tests/VirtualMachineTests.cs
…plit

- Split GrobArithmeticException into its own file (one public type per file).
- Guard negative distance in ValueStack.Peek; add internal Reset() to clear stack at Run entry.
- VirtualMachine.Run now resets the operand stack on entry so a prior exception-terminated run cannot leak values into a subsequent invocation.
- Tests: rename multi-underscore methods to Subject_BehaviourClause shape; add ex.Line assertions to IntModuloByZero/FloatDivideByZero/FloatModuloByZero.
Comment thread src/Grob.Vm/VirtualMachine.cs Fixed
Comment thread src/Grob.Vm/VirtualMachine.cs Fixed
- Chunk now stores a parallel per-byte _columns list; adds GetColumn(offset) reader and column-bearing WriteByte/WriteOpCode overloads. Legacy 2-arg overloads remain and record column=0 (sentinel for 'unknown').
- GrobRuntimeException gains a Column property and a 4-arg ctor; legacy 3-arg ctor forwards with column=0. GrobArithmeticException mirrors both ctors.
- VirtualMachine.Run tracks the column alongside the line and threads it into all five arithmetic-error throws (E5001..E5005). #if DEBUG trace is the only path that touches the new column on every iteration; Release reads it only on a throw.
- Tests: new ChunkColumnTests round-trips column per byte; IntModuloByZero/FloatDivideByZero/FloatModuloByZero now assert ex.Column end-to-end.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/Grob.Vm.Tests/VirtualMachineTests.cs (1)

349-357: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Assert the runtime error code in the overflow test.

This test checks line and stack count but not ex.Code. A code-mapping regression would pass unnoticed.

Proposed fix
         var ex = Assert.Throws<GrobRuntimeException>(
             () => stack.Push(GrobValue.FromInt(0), line: 99));
+        Assert.Equal("E5903", ex.Code);
         Assert.Equal(99, ex.Line);
         Assert.Equal(ValueStack.Capacity, stack.Count);
As per coding guidelines "Every test that exercises error output must assert the full diagnostic contract: exact diagnostic code, 1-based line number, and exact 1-based column number."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/Grob.Vm.Tests/VirtualMachineTests.cs` around lines 349 - 357, The test
ValueStackOverflow_SurfacesAsRuntimeErrorNotUnguardedWrite must assert the full
diagnostic contract: add assertions that the thrown GrobRuntimeException exposes
the exact diagnostic code and the 1-based column number in addition to existing
line and stack count checks; specifically, in that test assert ex.Code equals
the expected value-stack-overflow enum/constant (the project’s value-stack
overflow diagnostic code) and assert ex.Column == 1 (the expected 1-based
column).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Grob.Vm/ValueStack.cs`:
- Around line 66-70: The XML summary for Reset() is inaccurate: the method does
clear the live region using Array.Clear, so update the comment in ValueStack.cs
to state that Reset() clears the live slots (releasing references) and sets the
top pointer to zero; reference existing members Push() and Pop() in the summary
to clarify that Push will overwrite slots after Reset and Pop already clears
individual slots, ensuring the doc matches the implementation.

---

Outside diff comments:
In `@tests/Grob.Vm.Tests/VirtualMachineTests.cs`:
- Around line 349-357: The test
ValueStackOverflow_SurfacesAsRuntimeErrorNotUnguardedWrite must assert the full
diagnostic contract: add assertions that the thrown GrobRuntimeException exposes
the exact diagnostic code and the 1-based column number in addition to existing
line and stack count checks; specifically, in that test assert ex.Code equals
the expected value-stack-overflow enum/constant (the project’s value-stack
overflow diagnostic code) and assert ex.Column == 1 (the expected 1-based
column).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e0fa4e70-aaf4-4d87-ad2d-17f2c792533e

📥 Commits

Reviewing files that changed from the base of the PR and between 0b780a9 and d92368d.

📒 Files selected for processing (5)
  • src/Grob.Core/GrobArithmeticException.cs
  • src/Grob.Core/GrobRuntimeException.cs
  • src/Grob.Vm/ValueStack.cs
  • src/Grob.Vm/VirtualMachine.cs
  • tests/Grob.Vm.Tests/VirtualMachineTests.cs
💤 Files with no reviewable changes (1)
  • src/Grob.Core/GrobRuntimeException.cs
✅ Files skipped from review due to trivial changes (1)
  • src/Grob.Core/GrobArithmeticException.cs

Comment thread src/Grob.Vm/ValueStack.cs Outdated
Comment thread src/Grob.Vm/VirtualMachine.cs Fixed
Comment thread src/Grob.Vm/VirtualMachine.cs Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Grob.Core/Chunk.cs`:
- Around line 57-61: In Chunk.WriteByte(byte value, int line, int column) reject
negative column values by validating column >= 0 and throw an ArgumentException
(with a clear parameter name "column") when column < 0; update the method to
perform this guard before mutating _code, _lines, and _columns so no invalid
source metadata is added.

In `@src/Grob.Core/GrobRuntimeException.cs`:
- Around line 41-46: The public constructor GrobRuntimeException(string code,
int line, int column, string message) must validate inputs: throw
ArgumentNullException if code is null, ArgumentException if code is
empty/whitespace, ArgumentOutOfRangeException (or ArgumentException per
guidelines) if line < 1, and ArgumentOutOfRangeException if column < 0; add
these checks at the start of the constructor for Code, Line and Column and use
the specific exception types (ArgumentNullException and
ArgumentException/ArgumentOutOfRangeException) with clear parameter names to
enforce valid diagnostics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 106eb02b-af7b-48ec-a47f-46a1859335e3

📥 Commits

Reviewing files that changed from the base of the PR and between d92368d and b36b1bd.

📒 Files selected for processing (6)
  • src/Grob.Core/Chunk.cs
  • src/Grob.Core/GrobArithmeticException.cs
  • src/Grob.Core/GrobRuntimeException.cs
  • src/Grob.Vm/VirtualMachine.cs
  • tests/Grob.Core.Tests/ChunkColumnTests.cs
  • tests/Grob.Vm.Tests/VirtualMachineTests.cs

Comment thread src/Grob.Core/Chunk.cs
Comment thread src/Grob.Core/GrobRuntimeException.cs
kwakker35 added 2 commits May 26, 2026 22:07
- VirtualMachine.Run: SuppressMessage S3776 (cognitive complexity). Bytecode dispatch is a single switch by design per D-302; extracting per-opcode handlers would add a call frame per instruction.
- VirtualMachine DivideFloat/ModuloFloat: scoped #pragma warning disable S1244 around the b == 0.0 guards. Exact-zero check is intentional per D-273: +0.0/-0.0 both caught, NaN propagates as NaN, no tolerance bias on small divisors.
Comment thread src/Grob.Vm/VirtualMachine.cs Fixed
Comment thread src/Grob.Vm/VirtualMachine.cs Fixed
Comment thread src/Grob.Vm/VirtualMachine.cs Dismissed
Comment thread src/Grob.Vm/VirtualMachine.cs Dismissed
kwakker35 added 2 commits May 26, 2026 22:18
- ValueStack.Reset: docstring now matches behaviour (live region IS cleared via Array.Clear so reference slots are released to GC per D-304).
- Chunk.WriteByte(byte,int,int): rejects negative column with ArgumentOutOfRangeException. Columns are 1-based or 0 ('unknown'); negative values are never valid source metadata.
- GrobRuntimeException 4-arg ctor: validates code (non-null, non-empty), line (>= 1), column (>= 0), and message (non-null, non-empty) at the public boundary.
Mirror the validation added to GrobRuntimeException so the contract is enforced at the write boundary instead of only surfacing on a downstream throw. Line is always 1-based and never optional (unlike column, where 0 is a valid 'unknown' sentinel).
@sonarqubecloud

Copy link
Copy Markdown

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant