MobNew.Templates.Lint (mob_new v0.3.8)

Copy Markdown View Source

Structural lints for generator-rendered native source files.

EEx templates can produce output that string-match generator tests miss — duplicate imports, missing braces, orphan <%= tags. Real compilation would catch them but is expensive (needs Android SDK for Kotlin, Xcode for Swift, etc.). These lints are the cheap middle layer: language-agnostic structural checks that run in sub-second time on every mix test.

Each check returns a list of issue maps; the empty list means no problems. Aggregate functions (check_kotlin/1, check_c/1, check_swift/1) run all checks relevant to a language and return the combined issue list.

Use:

content = File.read!("path/to/MobBridge.kt")
assert MobNew.Templates.Lint.check_kotlin(content) == []

Or for finer-grained reporting:

content
|> MobNew.Templates.Lint.check_kotlin()
|> Enum.each(&IO.puts(&1.message))

Limits: structural only. A typo that produces still-balanced braces (x_funtion instead of x_function) won't be caught. See mix mob.lint_templates (planned) for a fuller battery that also invokes zig cc -fsyntax-only on rendered C.

Summary

Functions

Asserts equal counts of { and }. Naive — strings containing literal braces would skew the count, but template C/Kotlin/Swift output rarely has JSON or printf("{...}") strings.

Asserts equal counts of [ and ].

Asserts equal counts of ( and ).

Runs all C-relevant checks on the given content. Returns combined issue list.

Runs all Kotlin-relevant checks on the given content. Returns combined issue list (empty = clean).

Runs all Swift-relevant checks on the given content.

For Kotlin/C native bridges: every external fun nativeFoo(...) declared in the Kotlin file must have a matching Java_..._MobBridge_nativeFoo JNI thunk in the C file. Catches the "added the Kotlin extern but forgot the C side" regression (or vice versa). Pass both file contents.

Catches <%= / <% / %> left in rendered output. Indicates a malformed template tag or a render-pipeline misconfiguration that emitted the literal text instead of evaluating it.

Asserts every ^import line in Kotlin output is unique. kotlinc rejects duplicate imports with "Conflicting import" and the build fails. This was the bug class that hit 0.3.2 → 0.3.4 twice.

Asserts every ^import line in Swift output is unique. swiftc is more forgiving than kotlinc (warns rather than errors on duplicates) but Apple's archive-validation pass surfaces them.

Types

issue()

@type issue() :: %{kind: atom(), message: String.t()}

Functions

balanced_braces(content)

@spec balanced_braces(String.t()) :: [issue()]

Asserts equal counts of { and }. Naive — strings containing literal braces would skew the count, but template C/Kotlin/Swift output rarely has JSON or printf("{...}") strings.

balanced_brackets(content)

@spec balanced_brackets(String.t()) :: [issue()]

Asserts equal counts of [ and ].

balanced_parens(content)

@spec balanced_parens(String.t()) :: [issue()]

Asserts equal counts of ( and ).

check_c(content)

@spec check_c(String.t()) :: [issue()]

Runs all C-relevant checks on the given content. Returns combined issue list.

check_kotlin(content)

@spec check_kotlin(String.t()) :: [issue()]

Runs all Kotlin-relevant checks on the given content. Returns combined issue list (empty = clean).

check_swift(content)

@spec check_swift(String.t()) :: [issue()]

Runs all Swift-relevant checks on the given content.

external_fun_jni_consistency(kotlin_content, c_content)

@spec external_fun_jni_consistency(String.t(), String.t()) :: [issue()]

For Kotlin/C native bridges: every external fun nativeFoo(...) declared in the Kotlin file must have a matching Java_..._MobBridge_nativeFoo JNI thunk in the C file. Catches the "added the Kotlin extern but forgot the C side" regression (or vice versa). Pass both file contents.

The Java-class infix between Java_ and _native... is package-dependent; we just check the suffix matches.

no_eex_leaks(content)

@spec no_eex_leaks(String.t()) :: [issue()]

Catches <%= / <% / %> left in rendered output. Indicates a malformed template tag or a render-pipeline misconfiguration that emitted the literal text instead of evaluating it.

unique_kotlin_imports(content)

@spec unique_kotlin_imports(String.t()) :: [issue()]

Asserts every ^import line in Kotlin output is unique. kotlinc rejects duplicate imports with "Conflicting import" and the build fails. This was the bug class that hit 0.3.2 → 0.3.4 twice.

unique_swift_imports(content)

@spec unique_swift_imports(String.t()) :: [issue()]

Asserts every ^import line in Swift output is unique. swiftc is more forgiving than kotlinc (warns rather than errors on duplicates) but Apple's archive-validation pass surfaces them.