Skip to content

Comments

Engage persist compiler plugin with persist multi-model support#318

Merged
TharmiganK merged 9 commits intomainfrom
multi-model-support
Feb 19, 2026
Merged

Engage persist compiler plugin with persist multi-model support#318
TharmiganK merged 9 commits intomainfrom
multi-model-support

Conversation

@TharmiganK
Copy link
Contributor

@TharmiganK TharmiganK commented Feb 12, 2026

Purpose

$Subject

Before the multi-model support, only the model file in the persist directory gets the compiler validations for persist package. But with the new multi-model structure, we need to engage the compiler plugin to the sub-directories which represent the models

Part of: ballerina-platform/ballerina-library#8503

Examples

N/A

Checklist

  • Linked to an issue
  • Updated the specification
  • Updated the changelog
  • Added tests
  • Checked native-image compatibility

This pull request enables the persist compiler plugin to run validations in repositories that organize persistence models into multiple subdirectories. Previously the plugin only validated a single model file under persist/; with these changes it discovers model-specific metadata, scopes validations per model, and resolves per-model configuration.

Key changes

  • Model-aware configuration

    • Add logic to compute a model name and locate the associated Ballerina.toml for each model source file.
    • Make datastore resolution model-scoped so each model subdirectory can use its own configuration and filePath mappings.
    • Add constants for parsing model and filePath entries.
  • Validator updates

    • Update PersistModelDefinitionValidator to use the new model-discovery utilities and to short-circuit earlier when TOML paths, datastore info, or compilation errors are missing.
    • Add a helper to validate relation annotation field names.
  • Utilities and TOML parsing

    • Introduce PersistModelInformation and getPersistModelInfo(ctx) to surface modelName and TOML path per source file.
    • Refactor TOML parsing and datastore extraction to consider model and filePath conditions.
    • Expose getDatastore variants that accept explicit config paths and model names.
  • Tests and fixtures

    • Add unit tests and test resources covering multi-model scenarios: success and failure cases, field-type and record-property validations, and isolation between default and named models.
    • Add example project manifests and model files exercising model-specific datastore and filePath behaviors.
  • Release and metadata

    • Bump project and plugin versions from 1.6.1-SNAPSHOT to 1.7.0-SNAPSHOT.
    • Update changelog to document added multi-model validation support.

Outcome

  • The compiler plugin now discovers and validates multiple models within a repository, resolving per-model configuration so validations correctly apply to each model subdirectory.

@coderabbitai
Copy link

coderabbitai bot commented Feb 12, 2026

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

No actionable comments were generated in the recent review. 🎉


📝 Walkthrough

Walkthrough

Adds multi-model support: new PersistModelInformation and Utils APIs to locate Ballerina.toml and resolve model-specific datastores, Constants for MODEL/FILE_PATH, refactors PersistModelDefinitionValidator to use model info, expands compiler-plugin tests and test resources, and bumps versions to 1.7.0-SNAPSHOT.

Changes

Cohort / File(s) Summary
Changelog & Version
changelog.md, gradle.properties, ballerina/Ballerina.toml, ballerina/CompilerPlugin.toml, ballerina/Dependencies.toml
Added Unreleased "Added" entry for multi-model validations; bumped versions and updated plugin/artifact references to 1.7.0-SNAPSHOT.
Constants
compiler-plugin/src/main/java/.../Constants.java
Added MODEL and FILE_PATH constants.
Validator & Utils (core)
compiler-plugin/src/main/java/.../PersistModelDefinitionValidator.java, compiler-plugin/src/main/java/.../utils/Utils.java
Introduced PersistModelInformation and getPersistModelInfo(ctx); model-aware getDatastore(configPath, model) and TOML parsing helpers; refactored validator to use model info and added validateRelationAnnotationFieldName.
Compiler plugin tests
compiler-plugin-test/src/test/java/.../CompilerPluginTest.java
Added multi-model test helpers and multiple tests covering multi-model success/failure, field-type and record-property validation, and model isolation scenarios.
Test resources — project_12 (medical)
compiler-plugin-test/src/test/resources/project_12/Ballerina.toml, .../persist/medical/*
New project config for model "medical" (MySQL) and corresponding persist files: field-types, record-properties, and valid model path.
Test resources — project_13 (inventory)
compiler-plugin-test/src/test/resources/project_13/Ballerina.toml, .../persist/inventory/field-types.bal
New project config for inventory model (PostgreSQL) and comprehensive field-type definitions.
Test resources — project_14 (default + secondary)
compiler-plugin-test/src/test/resources/project_14/Ballerina.toml, .../persist/field-types.bal, .../persist/secondary/field-types.bal
New project with default datastore and named "secondary" model (PostgreSQL); added corresponding field-type files exercising model isolation.

Sequence Diagram(s)

sequenceDiagram
    participant Compiler as Compiler (SyntaxNodeAnalysisContext)
    participant Validator as PersistModelDefinitionValidator
    participant Utils as Utils
    participant FileSystem as Ballerina.toml / persist files

    Compiler->>Validator: provide SyntaxNodeAnalysisContext
    Validator->>Utils: getPersistModelInfo(ctx)
    Utils->>FileSystem: locate Ballerina.toml and persist entries (model, filePath)
    FileSystem-->>Utils: tomlPath + entries
    Utils-->>Validator: PersistModelInformation(modelName, tomlPath)
    Validator->>Utils: getDatastore(tomlPath, modelName)
    Utils->>FileSystem: extract datastore for matching model/filePath
    FileSystem-->>Utils: datastoreName
    Utils-->>Validator: datastoreName
    Validator->>Compiler: validate model definitions & emit diagnostics
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped through TOML and named each trail,

Found models hidden in file and vale,
Validators danced, checks snug and neat,
Multi-model fields now line the street,
A rabbit celebrates with a happy tail.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the main change: engaging the persist compiler plugin to support multi-model validation scenarios, which aligns with all file modifications.

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

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch multi-model-support

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

@codecov
Copy link

codecov bot commented Feb 12, 2026

Codecov Report

❌ Patch coverage is 81.81818% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.79%. Comparing base (4dae7a3) to head (6e4aea2).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ballerina/stdlib/persist/compiler/utils/Utils.java 80.48% 6 Missing and 10 partials ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #318      +/-   ##
============================================
+ Coverage     87.71%   87.79%   +0.08%     
- Complexity      373      389      +16     
============================================
  Files            30       30              
  Lines          1188     1229      +41     
  Branches        149      153       +4     
============================================
+ Hits           1042     1079      +37     
- Misses           92       94       +2     
- Partials         54       56       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@compiler-plugin-test/src/test/resources/project_12/Ballerina.toml`:
- Around line 6-9: The TOML entry under [[tool.persist]] points filePath to
"persist/medical/model.bal" which does not exist; change the filePath value to
one of the actual model files in persist/medical (for example
"persist/medical/valid-persist-model-path.bal" or the appropriate model file
among "field-types.bal"/"record-properties.bal") so the [[tool.persist]]
configuration references an existing model file; update the filePath key in the
Ballerina.toml accordingly.

In `@compiler-plugin-test/src/test/resources/project_13/Ballerina.toml`:
- Around line 6-9: The Ballerina.toml entry under [[tool.persist]] for id
"project13" references a non-existent model file via filePath
"persist/inventory/model.bal"; either add the missing file at that path or
update the filePath to the correct existing file (e.g.,
"persist/inventory/field-types.bal") so the tool.persist configuration points to
a valid model file and the project can resolve the model during compilation.

In `@compiler-plugin-test/src/test/resources/project_14/Ballerina.toml`:
- Around line 6-12: The Ballerina.toml references non-existent model.bal files
under the [[tool.persist]] entries; either update the file paths or rename test
files—easiest fix: change the persist filePath values to point to the existing
field-types.bal files (e.g., set the primary [[tool.persist]] to use filePath
"persist/field-types.bal" and the secondary [[tool.persist]] to use filePath
"persist/secondary/field-types.bal"), keeping the existing
options.datastore/model keys intact so the runtime finds the correct resource
files.

In
`@compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/utils/Utils.java`:
- Around line 188-190: In Utils.java replace the empty catch block for
UnsupportedOperationException in the path-resolution code with proper logging:
obtain the project logger used across the module (e.g., a class-level org.slf4j
Logger in Utils) and call logger.error or logger.warn with a clear message like
"Failed to resolve path" and include the exception (e) so the stacktrace is
recorded; if the resolution failure should stop processing, rethrow or wrap the
exception (e.g., throw new RuntimeException(..., e)) instead of silently
swallowing it.
🧹 Nitpick comments (3)
compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/PersistModelDefinitionValidator.java (1)

134-139: Consider more specific exception handling.

Wrapping the checked BalException in an unchecked RuntimeException loses context and could make debugging difficult. Consider logging the error or using a more specific runtime exception with a descriptive message.

Proposed improvement
         try {
             datastore = getDatastore(ballerinaTomlPath, persistModelInformation.modelName());
         } catch (BalException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to resolve datastore for model: " + 
+                    persistModelInformation.modelName(), e);
         }
compiler-plugin-test/src/test/java/io/ballerina/stdlib/persist/compiler/CompilerPluginTest.java (1)

819-827: Test comment implies new behavior but tests existing project.

The comment states "A file in a non-persist subdirectory should not be identified as a model file", but this test uses project_1/resources, which is the same as the existing identifyModelFileFailure2 test. Consider using a multi-model project directory to specifically test multi-model edge cases.

compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/utils/Utils.java (1)

361-363: Potential NPE if field.value() returns null.

The getValue method calls field.value().toSourceCode() without null-checking field.value(). While TOML syntax typically requires values, defensive programming would add a null check.

Proposed defensive null check
     private static String getValue(KeyValueNode field) {
-        return field.value().toSourceCode().trim().replace("\"", "");
+        var value = field.value();
+        return value != null ? value.toSourceCode().trim().replace("\"", "") : null;
     }

@coderabbitai
Copy link

coderabbitai bot commented Feb 12, 2026

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #319

coderabbitai bot added a commit that referenced this pull request Feb 12, 2026
Docstrings generation was requested by @TharmiganK.

* #318 (comment)

The following files were modified:

* `compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/PersistModelDefinitionValidator.java`
* `compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/utils/Utils.java`
@TharmiganK TharmiganK closed this Feb 12, 2026
@TharmiganK TharmiganK reopened this Feb 12, 2026
@TharmiganK TharmiganK marked this pull request as draft February 12, 2026 10:25
@TharmiganK TharmiganK marked this pull request as ready for review February 12, 2026 10:57
@TharmiganK TharmiganK requested a review from Copilot February 12, 2026 10:57
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the persist compiler plugin to apply validations for the new multi-model persist directory structure by resolving the correct model context (model name + associated Ballerina.toml) and selecting model-specific datastore configuration.

Changes:

  • Added persist model resolution utilities (model name + Ballerina.toml path) and updated datastore resolution to be model-aware.
  • Updated PersistModelDefinitionValidator to use model info + model-scoped datastore lookup for validations.
  • Added multi-model test fixtures and new test cases; bumped module/plugin versions and updated changelog.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
gradle.properties Bumps project version to 1.7.0-SNAPSHOT.
compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/utils/Utils.java Adds model discovery + model-aware datastore extraction from TOML.
compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/PersistModelDefinitionValidator.java Switches validation entry logic to use resolved model/TOML info and model-scoped datastore lookup.
compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/Constants.java Introduces model and filePath TOML key constants.
compiler-plugin-test/src/test/resources/project_14/persist/secondary/field-types.bal Adds multi-model fixture file.
compiler-plugin-test/src/test/resources/project_14/persist/field-types.bal Adds default-model fixture file.
compiler-plugin-test/src/test/resources/project_14/Ballerina.toml Adds TOML with default + named model [[tool.persist]] entries.
compiler-plugin-test/src/test/resources/project_13/persist/inventory/field-types.bal Adds multi-model fixture file.
compiler-plugin-test/src/test/resources/project_13/Ballerina.toml Adds model selection via filePath fixture.
compiler-plugin-test/src/test/resources/project_12/persist/medical/valid-persist-model-path.bal Adds multi-model fixture for model detection.
compiler-plugin-test/src/test/resources/project_12/persist/medical/record-properties.bal Adds multi-model fixture for record validations.
compiler-plugin-test/src/test/resources/project_12/persist/medical/field-types.bal Adds multi-model fixture for type validations.
compiler-plugin-test/src/test/resources/project_12/Ballerina.toml Adds multi-model TOML fixture for model selection.
compiler-plugin-test/src/test/java/io/ballerina/stdlib/persist/compiler/CompilerPluginTest.java Adds multi-model test coverage and helpers.
changelog.md Notes multi-model validation support in Unreleased section.
ballerina/Dependencies.toml Bumps dependency version to 1.7.0.
ballerina/CompilerPlugin.toml Updates embedded plugin jar path to 1.7.0-SNAPSHOT.
ballerina/Ballerina.toml Bumps package and platform dependency versions/paths to 1.7.0.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In
`@compiler-plugin/src/main/java/io/ballerina/stdlib/persist/compiler/utils/Utils.java`:
- Around line 198-208: getPersistModelInfo currently only handles
SINGLE_FILE_PROJECT and returns an empty PersistModelInformation for
BuildProject/other kinds, causing PersistModelDefinitionValidator.perform to
skip validations; fix by adding an else branch that resolves the current
document's path for non-single-file projects (use the SyntaxNodeAnalysisContext
APIs to get the source file path for the node—e.g., obtain the file path from
ctx.node().location().lineRange().filePath() or the equivalent filePath()
accessor exposed by the analysis/context API) and pass that resolved Path into
getPersistModelInformation so getPersistModelInfo returns a populated
PersistModelInformation for BuildProject too; keep the try/catch for
UnsupportedOperationException and ensure no null ballerinaTomlPath is returned.

daneshk
daneshk previously approved these changes Feb 17, 2026
Copy link
Member

@daneshk daneshk left a comment

Choose a reason for hiding this comment

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

Let's add License headers to test resource files. Others LGTM

@sonarqubecloud
Copy link

@TharmiganK TharmiganK merged commit 0fd5ce0 into main Feb 19, 2026
8 of 9 checks passed
@TharmiganK TharmiganK deleted the multi-model-support branch February 19, 2026 06:35
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.

2 participants