feat(compiler): SYN011 — warn on dynamic import() calls that bypass the module capability model (?bs 0.7+)#153
Open
marcelofarias wants to merge 4 commits into
Open
feat(compiler): SYN011 — warn on dynamic import() calls that bypass the module capability model (?bs 0.7+)#153marcelofarias wants to merge 4 commits into
marcelofarias wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for the new SYN011 warning by documenting it, registering it in the error-code registry, explaining it via the MCP server, and implementing + testing detection of dynamic import() calls inside function bodies.
Changes:
- Register and document new diagnostic code
SYN011across compiler/MCP surfaces (README, AGENTS, explanations/registry). - Implement
SYN011detection in the compiler syn-check pass forimport(specifier)within fn bodies (suppressed inunsafe). - Add compiler tests validating triggering/suppression, severity, and version gating behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/mcp/tests/server.test.ts | Includes SYN011 in MCP “explainable codes” coverage. |
| packages/mcp/src/explanations.ts | Adds long-form MCP explanation + examples for SYN011. |
| packages/compiler/tests/syn011-check.test.ts | Adds vitest coverage for SYN011 detection/suppression semantics. |
| packages/compiler/tests/error-codes.test.ts | Registers SYN011 in the compiler’s error-code registry test. |
| packages/compiler/src/passes/syn-check.ts | Implements the SYN011 token scan + warning emission. |
| packages/compiler/src/error-codes.ts | Adds compiler registry entry (title/rule/idiom/rewrite/example) for SYN011. |
| README.md | Documents SYN011 as a valid explain target. |
| AGENTS.md | Adds SYN011 to the diagnostics table and remediation guidance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
1664d42 to
327da66
Compare
9234bd2 to
6847365
Compare
…he module capability model (?bs 0.7+)
- Adds SYN011: fires when a fn body calls import(specifier) — the dynamic import form
- Dynamic imports load a module at runtime whose capability surface is unbounded:
CAP001 cannot see what the dynamically loaded module does; the fn header cannot
declare capabilities it doesn't know about at compile time
- import.meta (followed by `.`) is excluded — it's a property, not a call
- Suppressed inside `unsafe "reason" { }` blocks and `unsafe "reason" fn` bodies
- 10 tests: bare/template-literal/awaited forms, unsafe suppression, import.meta
exclusion, version gate, severity, multi-call count, bare reference non-fire
- Should be merged after SYN010 (PR #151) lands — SYN011 is the next available code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t error reporting
…and exclusion and test guards
- Add fn/function declaration exclusion for SYN011 (mirrors SYN010 pattern)
- Add method shorthand exclusion: { import(x) { ... } } after matching closing ) check
- Simplify compile() helper in syn011-check.test.ts to match syn010 pattern
- Add regression test: SYN011 does NOT fire on object method shorthand named import
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
f9369b5 to
3b596f2
Compare
Comment on lines
+702
to
+704
| // Exclude fn / function declarations: `fn import(...)` or `function import(...)` | ||
| if (prev11 && prev11.kind === "ident" && (prev11.text === "fn" || prev11.text === "function")) | ||
| continue; |
…aration exclusion
Botscript's `fn` keyword is lexed as kind="keyword", not kind="ident".
The previous exclusion check (`prev11.kind === "ident" && prev11.text === "fn"`)
never matched, so `fn import(specifier) { ... }` declarations were incorrectly
flagged as SYN011. Fix to check kind==="keyword" for `fn` and kind==="ident"
for `function`. Adds regression test to prevent future regressions.
Co-Authored-By: Botkowski <noreply@botkowski>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
import(...)— the dynamic import form — at?bs 0.7+http.*member calls). The fn header cannot declare capabilities it doesn't know about at compile timeunsafe "reason" { }blocks andunsafe "reason" fnbodiesChanges
packages/compiler/src/error-codes.tspackages/compiler/src/passes/syn-check.tspackages/compiler/tests/syn011-check.test.tspackages/compiler/tests/error-codes.test.tspackages/mcp/src/explanations.tspackages/mcp/tests/server.test.tsAGENTS.mdREADME.mdexplaintool code listTest plan
pnpm -r build && pnpm test— 1171 tests pass (42 test files)import(specifier)import(`./module`)const mod = await import(path)unsafe {}blocks andunsafe fnbodiesimport.meta.url(property access, not a call)?bs 0.7