Skip to content

fix(ios): NSError** runtime fallback and enriched arg-count diagnostics#382

Open
NathanWalker wants to merge 2 commits into
mainfrom
fix/nserror-out-param-and-diagnostics
Open

fix(ios): NSError** runtime fallback and enriched arg-count diagnostics#382
NathanWalker wants to merge 2 commits into
mainfrom
fix/nserror-out-param-and-diagnostics

Conversation

@NathanWalker
Copy link
Copy Markdown
Contributor

@NathanWalker NathanWalker commented Jun 3, 2026

  • improved error visibility around NSError** out-parameter handling

Runtime:

  • Metadata.h: hasErrorOutParameter() now falls back to inspecting the last binary type encoding when the MethodHasErrorOutParameter flag is clear. Mirrors what ArgConverter::IsErrorOutParameter already does on the callback path. Lets apps shipping older/buggy metadata recover correct auto-NSError** handling without regenerating metadata.

Diagnostics:

  • ArgConverter.mm: argument-count error message had its Actual/Expected labels swapped and no call-site context. Fixed the swap and added method kind, JS name, class name, full Objective-C selector, and a conditional hint when the method has an NSError** out-parameter that callers may omit.
  • ObjectManager.mm: ReleaseNativeCounterpartCallback error message now names the function it is about (__releaseNativeCounterpart).

Summary by CodeRabbit

  • Bug Fixes
    • Improved error messaging for argument-count mismatches, now correctly reporting actual vs. expected parameter counts with additional context about method type and class information.
    • Enhanced error parameter detection for more reliable method signature validation across modern SDK annotations.

Adds defensive coverage and improved error visibility around NSError**
out-parameter handling on modern iOS SDKs.

Runtime:
- Metadata.h: hasErrorOutParameter() now falls back to inspecting the
  last binary type encoding when the MethodHasErrorOutParameter flag is
  clear. Mirrors what ArgConverter::IsErrorOutParameter already does on
  the callback path. Lets apps shipping older/buggy metadata recover
  correct auto-NSError** handling without regenerating metadata.

Diagnostics:
- ArgConverter.mm: argument-count error message had its Actual/Expected
  labels swapped and no call-site context. Fixed the swap and added
  method kind, JS name, class name, full Objective-C selector, and a
  conditional hint when the method has an NSError** out-parameter that
  callers may omit.
- ObjectManager.mm: ReleaseNativeCounterpartCallback error message now
  names the function it is about (__releaseNativeCounterpart).

Documentation:
- MetaFactory.cpp: explanatory comment block documenting why the
  existing NullableType unwrap (already on main via #367) is needed
  for "NSError * _Nullable * _Nullable" selectors on modern SDKs.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR enhances NSError out-parameter detection and improves argument-mismatch error messages across the NativeScript runtime. Metadata detection now infers NSError parameters from serialized type encodings when metadata flags are unset, and error messages in argument validation include method context, selector information, and conditional accounting for hidden NSError parameters.

Changes

NSError Detection and Error Messaging

Layer / File(s) Summary
NSError detection inference in metadata
NativeScript/runtime/Metadata.h
Added <cstring> header and enhanced MethodMeta::hasErrorOutParameter() to perform two-stage detection: check the explicit flag first, then fall back to inspecting method type encodings to infer a pointer-to-NSError last parameter.
Error message improvements
NativeScript/runtime/ArgConverter.mm, NativeScript/runtime/ObjectManager.mm
ArgConverter and ObjectManager now produce richer argument-count mismatch errors that include method kind, JS/function names, class names, selectors, and conditionally document the expected count excluding NSError** when present.
NSError detection documentation
metadata-generator/src/Meta/MetaFactory.cpp
Added detailed comment explaining how NSError** out-parameters wrapped in nullability annotations are unwrapped through both pointer and interface levels to set the detection flag correctly.

🎯 3 (Moderate) | ⏱️ ~20 minutes


🐰 Errors now speak clear and true,
With NSError threads we'll pursue,
From metadata's hint to messages bright,
Each mismatch now debugged just right!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: NSError** runtime fallback mechanism and enriched argument-count diagnostic messages across multiple files.
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 docstrings
  • Create stacked PR
  • Commit on current branch

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Infer (1.2.0)
metadata-generator/src/Meta/MetaFactory.cpp

In file included from metadata-generator/src/Meta/MetaFactory.cpp:1:
In file included from metadata-generator/src/Meta/MetaFactory.h:3:
In file included from metadata-generator/src/Meta/CreationException.h:5:
In file included from metadata-generator/src/Meta/MetaEntities.h:4:
metadata-generator/src/Meta/TypeEntities.h:7:10: fatal error: 'Utils/Noncopyable.h' file not found
7 | #include "Utils/Noncopyable.h"
| ^~~~~~~~~~~~~~~~~~~~~
1 error generated.
metadata-generator/src/Meta/MetaFactory.cpp:33:40-46:1: ERROR translating statement 'CompoundStmt'
Aborting translation of method 'Meta::MetaFactory::validate' in file 'metadata-generator/src/Meta/MetaFactory.cpp': "Assert_failure src/clang/cAst_utils.ml:249:53"
Uncaught Internal Error: "Assert_failure src/clang/cAst_utils.ml:249:53"
Error backtrace:
Raised at ClangFrontend__CAst_utils.get_decl_from_typ_ptr in file "src/clang/cAst_utils.ml", line 249, characters 53-65
Called from ClangFrontend__CTrans.CTrans_funct.get_des

... [truncated 2200 characters] ...

10
Re-raised at IStdlib__IExn.reraise_if in file "src/istd/IExn.ml" (inlined), line 18, characters 15-63
Called from ClangFrontend__CFrontend_errors.protect in file "src/clang/cFrontend_errors.ml", line 48, characters 6-141
Called from ClangFrontend__CFrontend_decl.CFrontend_decl_funct.add_method in file "src/clang/cFrontend_decl.ml" (inlined), line 54, characters 4-52
Called from ClangFrontend__CFrontend_decl.CFrontend_decl_funct.process_method_decl.add_method_if_create_procdesc in file "src/clang/cFrontend_decl.ml" (inlined), line 123, characters 16-158
Called from ClangFrontend__CFrontend_decl.CFrontend_decl_funct.process_method_decl in file "src/clang/cFrontend_decl.ml", line 126, characters 17-97
Called from ClangFrontend__CFrontend_decl.CFrontend_decl_funct.process_methods in file "s


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@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

🤖 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 `@NativeScript/runtime/ArgConverter.mm`:
- Around line 113-124: The error message always formats the Objective-C selector
as an instance selector "-[Class selector]" even when reporting a static method;
update the string construction around errorStream (where methodKindStr is
computed from instanceMethod) to choose "+[" when instanceMethod is false so the
selector is printed as "+[Class selector]" for class methods; modify the logic
that appends " (selector: -[" << classNameStr << " " << selectorStr << "])" to
switch the prefix based on instanceMethod (use methodKindStr or a conditional to
select "+" vs "-") so jsNameStr, classNameStr and selectorStr remain unchanged
but the selector punctuation correctly reflects instance vs static methods.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: e5c8c3a2-db60-41c4-b69e-6563f1bbd9a5

📥 Commits

Reviewing files that changed from the base of the PR and between debf7f8 and dd38ab3.

📒 Files selected for processing (4)
  • NativeScript/runtime/ArgConverter.mm
  • NativeScript/runtime/Metadata.h
  • NativeScript/runtime/ObjectManager.mm
  • metadata-generator/src/Meta/MetaFactory.cpp

Comment on lines +113 to +124
const char* methodKindStr = instanceMethod ? "instance" : "static";

std::ostringstream errorStream;
errorStream << "Actual arguments count: \"" << argsCount << ". Expected: \"" << args.Length()
<< "\".";
errorStream << "Actual arguments count: \"" << args.Length() << "\". Expected: \"" << argsCount
<< "\"";
if (meta && meta->hasErrorOutParameter()) {
errorStream << " (or \"" << (argsCount - 1)
<< "\" if omitting the trailing NSError** out-parameter)";
}
errorStream << " for " << methodKindStr << " method \"" << jsNameStr << "\" on class \""
<< classNameStr << "\" (selector: -[" << classNameStr << " " << selectorStr
<< "]).";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use +[ when formatting static-method selectors.

Line 123 always renders the Objective-C selector as -[Class selector]. For class methods, the message now says static method but still prints an instance selector, which makes the new call-site context misleading.

Proposed fix
     const char* classNameStr = klass ? class_getName(klass) : "<unknown>";
     const char* methodKindStr = instanceMethod ? "instance" : "static";
+    const char selectorKind = instanceMethod ? '-' : '+';
 
     std::ostringstream errorStream;
     errorStream << "Actual arguments count: \"" << args.Length() << "\". Expected: \"" << argsCount
                 << "\"";
     if (meta && meta->hasErrorOutParameter()) {
@@
     }
     errorStream << " for " << methodKindStr << " method \"" << jsNameStr << "\" on class \""
-                << classNameStr << "\" (selector: -[" << classNameStr << " " << selectorStr
+                << classNameStr << "\" (selector: " << selectorKind << "[" << classNameStr << " " << selectorStr
                 << "]).";
🤖 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 `@NativeScript/runtime/ArgConverter.mm` around lines 113 - 124, The error
message always formats the Objective-C selector as an instance selector "-[Class
selector]" even when reporting a static method; update the string construction
around errorStream (where methodKindStr is computed from instanceMethod) to
choose "+[" when instanceMethod is false so the selector is printed as "+[Class
selector]" for class methods; modify the logic that appends " (selector: -[" <<
classNameStr << " " << selectorStr << "])" to switch the prefix based on
instanceMethod (use methodKindStr or a conditional to select "+" vs "-") so
jsNameStr, classNameStr and selectorStr remain unchanged but the selector
punctuation correctly reflects instance vs static methods.

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