Skip to content

Conversation

@lambdalisue
Copy link
Member

@lambdalisue lambdalisue commented Jul 20, 2025

Reverts #447

Summary by CodeRabbit

  • New Features

    • Introduced a new plugin management system that supports loading, unloading, and calling plugin APIs, with improved error handling and import map support.
    • Added comprehensive tests covering plugin lifecycle, error handling, and import map integration.
    • Added new test plugins and helper modules demonstrating import map usage.
  • Refactor

    • Refactored internal plugin management logic to use the newly introduced external plugin class for improved modularity.
  • Chores

    • Updated configuration to exclude additional test data directories from certain Deno operations.

@coderabbitai
Copy link

coderabbitai bot commented Jul 20, 2025

Walkthrough

A new Plugin class is introduced in a dedicated module to manage Denops plugin lifecycles, supporting import maps and hot reloading. The internal plugin logic is removed from the service module, which now depends on the new class. Comprehensive tests and test data for import map support are added, and configuration is updated to exclude new test directories.

Changes

File(s) Change Summary
denops/@denops-private/plugin.ts New Plugin class added for plugin lifecycle management, import map support, and hot reloading.
denops/@denops-private/service.ts Internal Plugin class and helpers removed; now imports and uses external Plugin class.
denops/@denops-private/plugin_test.ts New test suite for Plugin class, covering lifecycle, error handling, import map, and dispatcher.
tests/denops/testdata/with_import_map/helper.ts New helper module exporting a string and a function for import map testing.
tests/denops/testdata/with_import_map/import_map.json New import map JSON file with module path aliases for test plugins.
tests/denops/testdata/with_import_map/import_map.jsonc New import map JSONC file with comments and the same aliases as above.
tests/denops/testdata/with_import_map/plugin_with_import_map.ts New Denops plugin using import map aliases and helper module.
deno.jsonc Excludes tests/denops/testdata/with_import_map/ from Deno operations.

Sequence Diagram(s)

sequenceDiagram
    participant Service
    participant Plugin
    participant Denops
    participant PluginScript

    Service->>Plugin: new Plugin(denops, name, script)
    Plugin->>Plugin: resolve script URL (+suffix)
    Plugin->>Plugin: search for import map
    Plugin->>PluginScript: dynamic import (with/without import map)
    PluginScript-->>Plugin: exports main(denops)
    Plugin->>Denops: emit "plugin:pre:load"
    Plugin->>PluginScript: call main(denops)
    PluginScript-->>Plugin: returns disposable
    Plugin->>Denops: emit "plugin:post:load"
    Service->>Plugin: call(fn, ...args)
    Plugin->>PluginScript: dispatcher[fn](...args)
    PluginScript-->>Plugin: result
    Service->>Plugin: unload()
    Plugin->>Denops: emit "plugin:pre:unload"
    Plugin->>PluginScript: dispose()
    Plugin->>Denops: emit "plugin:post:unload"
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes
The changes involve a new complex class with asynchronous lifecycle management, error handling, import map support, and hot reloading logic, plus a comprehensive test suite and new test data files. The removal of internal plugin code from service.ts and its replacement with the new class requires careful review.

Possibly related PRs

  • vim-denops/denops.vim#446: Introduces the same Plugin class and removes the internal class from service.ts, indicating a direct code-level relationship.
  • vim-denops/denops.vim#447: Reverts the import map support and related test data introduced in this PR, directly affecting the same code and features.

Suggested labels

enhancement

Suggested reviewers

  • Shougo

Poem

A Plugin hops in, so spry and new,
With import maps and tests to chew.
Old code is cleared, the path is bright,
Hot reloads gleam in the moon’s soft light.
Now Denops plugins leap with glee—
More modular, mapped, and bug-free!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 83729d6 and 5cb86cb.

📒 Files selected for processing (1)
  • denops/@denops-private/plugin.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
Learnt from: Milly
PR: vim-denops/denops.vim#385
File: autoload/denops/plugin.vim:56-58
Timestamp: 2024-07-05T15:37:46.867Z
Learning: In the Denops.vim project, the `denops#plugin#unload()` function is designed to throw exceptions to the caller, who is responsible for handling them.
Learnt from: Milly
PR: vim-denops/denops.vim#335
File: denops/@denops-private/service.ts:245-259
Timestamp: 2024-07-27T10:03:47.237Z
Learning: The `emit` function in the Denops plugin system catches and logs errors internally, ensuring it does not throw errors to the caller.
denops/@denops-private/plugin.ts (4)

Learnt from: Milly
PR: #385
File: autoload/denops/plugin.vim:56-58
Timestamp: 2024-07-05T15:37:46.867Z
Learning: In the Denops.vim project, the denops#plugin#unload() function is designed to throw exceptions to the caller, who is responsible for handling them.

Learnt from: lambdalisue
PR: #344
File: denops/@denops-private/service.ts:183-183
Timestamp: 2024-07-08T01:52:22.851Z
Learning: In the denops/@denops-private/service.ts file, initializing properties like #loadedWaiter in the constructor is a common and acceptable pattern.

Learnt from: Milly
PR: #335
File: denops/@denops-private/service.ts:245-259
Timestamp: 2024-07-27T10:03:47.237Z
Learning: The emit function in the Denops plugin system catches and logs errors internally, ensuring it does not throw errors to the caller.

Learnt from: Milly
PR: #418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with /denops-testdata/ are defined in deno.jsonc via an import map, and these import paths are valid.

🪛 Biome (2.1.2)
denops/@denops-private/plugin.ts

[error] 20-20: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: test (macos-latest, 1.45.0, v9.1.0448, v0.10.0)
  • GitHub Check: test (macos-latest, 2.x, v9.1.0448, v0.10.0)
  • GitHub Check: test (ubuntu-latest, 1.x, v9.1.0448, v0.10.0)
  • GitHub Check: test (ubuntu-latest, 2.x, v9.1.0448, v0.10.0)
  • GitHub Check: test (ubuntu-latest, 1.45.0, v9.1.0448, v0.10.0)
  • GitHub Check: test (macos-latest, 1.x, v9.1.0448, v0.10.0)
  • GitHub Check: test (windows-latest, 1.45.0, v9.1.0448, v0.10.0)
  • GitHub Check: test (windows-latest, 1.x, v9.1.0448, v0.10.0)
  • GitHub Check: test (windows-latest, 2.x, v9.1.0448, v0.10.0)
🔇 Additional comments (7)
denops/@denops-private/plugin.ts (7)

1-10: Import statements look good.

The imports are well-organized and use appropriate JSR modules with proper version constraints. The import-map-importer dependency aligns with the PR objective of supporting import_map.json[c] files.


12-14: Type definition is appropriate.

The PluginModule type correctly defines the expected structure for plugin modules with a required main entrypoint.


32-60: Excellent plugin loading implementation.

The loading logic is comprehensive with proper lifecycle event emission, robust error handling, and helpful user guidance for known Deno cache issues. The implementation correctly captures the plugin's disposable resource for cleanup.


62-88: Well-designed unloading implementation.

The unloading logic properly handles the plugin lifecycle with atomic operations (waiting for load completion), resource disposal using async disposables, and comprehensive error handling. The memoization pattern prevents multiple unload operations.


90-101: Solid error handling in call method.

The call method properly delegates to the dispatcher and provides excellent error context, preferring stack traces when available and handling non-Error objects gracefully.


104-189: Excellent utility function implementations.

The utility functions are well-designed and comprehensive:

  • Hot reloading support with timestamp-based cache busting
  • Safe event emission that never throws
  • Robust import map support searching common file locations
  • Proper error detection for known Deno cache issues
  • Clean integration of import map functionality with native imports

The import map support correctly implements the PR objective of supporting import_map.json[c] files in plugin directories.


16-189: Strong architectural design.

This Plugin class provides excellent encapsulation of plugin lifecycle management with modern TypeScript patterns. The modular design, comprehensive error handling, import map support, and hot reloading functionality create a robust foundation for the Denops plugin system.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch revert-447-revert-446-support-import-map

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lambdalisue lambdalisue marked this pull request as draft July 20, 2025 04:20
@codecov
Copy link

codecov bot commented Jul 20, 2025

Codecov Report

❌ Patch coverage is 93.25153% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.52%. Comparing base (0a8841c) to head (5cb86cb).
⚠️ Report is 3 commits behind head on main.

Files with missing lines Patch % Lines
denops/@denops-private/plugin.ts 93.20% 10 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #450      +/-   ##
==========================================
- Coverage   96.97%   96.52%   -0.45%     
==========================================
  Files          26       27       +1     
  Lines        1421     1468      +47     
  Branches      182      192      +10     
==========================================
+ Hits         1378     1417      +39     
- Misses         40       47       +7     
- Partials        3        4       +1     

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a8841c and 83729d6.

📒 Files selected for processing (8)
  • deno.jsonc (1 hunks)
  • denops/@denops-private/plugin.ts (1 hunks)
  • denops/@denops-private/plugin_test.ts (1 hunks)
  • denops/@denops-private/service.ts (1 hunks)
  • tests/denops/testdata/with_import_map/helper.ts (1 hunks)
  • tests/denops/testdata/with_import_map/import_map.json (1 hunks)
  • tests/denops/testdata/with_import_map/import_map.jsonc (1 hunks)
  • tests/denops/testdata/with_import_map/plugin_with_import_map.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
Learnt from: Milly
PR: vim-denops/denops.vim#385
File: autoload/denops/plugin.vim:56-58
Timestamp: 2024-07-05T15:37:46.867Z
Learning: In the Denops.vim project, the `denops#plugin#unload()` function is designed to throw exceptions to the caller, who is responsible for handling them.
Learnt from: Milly
PR: vim-denops/denops.vim#335
File: denops/@denops-private/service.ts:245-259
Timestamp: 2024-07-27T10:03:47.237Z
Learning: The `emit` function in the Denops plugin system catches and logs errors internally, ensuring it does not throw errors to the caller.
deno.jsonc (1)
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
tests/denops/testdata/with_import_map/import_map.jsonc (1)
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
tests/denops/testdata/with_import_map/import_map.json (1)
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
tests/denops/testdata/with_import_map/helper.ts (1)
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
tests/denops/testdata/with_import_map/plugin_with_import_map.ts (1)
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
denops/@denops-private/plugin.ts (4)
Learnt from: Milly
PR: vim-denops/denops.vim#385
File: autoload/denops/plugin.vim:56-58
Timestamp: 2024-07-05T15:37:46.867Z
Learning: In the Denops.vim project, the `denops#plugin#unload()` function is designed to throw exceptions to the caller, who is responsible for handling them.
Learnt from: Milly
PR: vim-denops/denops.vim#335
File: denops/@denops-private/service.ts:245-259
Timestamp: 2024-07-27T10:03:47.237Z
Learning: The `emit` function in the Denops plugin system catches and logs errors internally, ensuring it does not throw errors to the caller.
Learnt from: lambdalisue
PR: vim-denops/denops.vim#344
File: denops/@denops-private/service.ts:183-183
Timestamp: 2024-07-08T01:52:22.851Z
Learning: In the `denops/@denops-private/service.ts` file, initializing properties like `#loadedWaiter` in the constructor is a common and acceptable pattern.
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
denops/@denops-private/plugin_test.ts (3)
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
Learnt from: Milly
PR: vim-denops/denops.vim#385
File: autoload/denops/plugin.vim:56-58
Timestamp: 2024-07-05T15:37:46.867Z
Learning: In the Denops.vim project, the `denops#plugin#unload()` function is designed to throw exceptions to the caller, who is responsible for handling them.
Learnt from: Milly
PR: vim-denops/denops.vim#335
File: denops/@denops-private/service.ts:245-259
Timestamp: 2024-07-27T10:03:47.237Z
Learning: The `emit` function in the Denops plugin system catches and logs errors internally, ensuring it does not throw errors to the caller.
denops/@denops-private/service.ts (5)
Learnt from: Milly
PR: vim-denops/denops.vim#385
File: autoload/denops/plugin.vim:56-58
Timestamp: 2024-07-05T15:37:46.867Z
Learning: In the Denops.vim project, the `denops#plugin#unload()` function is designed to throw exceptions to the caller, who is responsible for handling them.
Learnt from: lambdalisue
PR: vim-denops/denops.vim#344
File: denops/@denops-private/service.ts:183-183
Timestamp: 2024-07-08T01:52:22.851Z
Learning: In the `denops/@denops-private/service.ts` file, initializing properties like `#loadedWaiter` in the constructor is a common and acceptable pattern.
Learnt from: Milly
PR: vim-denops/denops.vim#352
File: denops/@denops-private/testutil/host.ts:3-4
Timestamp: 2024-07-27T10:03:47.237Z
Learning: `Neovim` and `Vim` from `../host/nvim.ts` and `../host/vim.ts` are classes and should be imported normally if they are instantiated in the code.
Learnt from: Milly
PR: vim-denops/denops.vim#335
File: denops/@denops-private/service.ts:245-259
Timestamp: 2024-07-27T10:03:47.237Z
Learning: The `emit` function in the Denops plugin system catches and logs errors internally, ensuring it does not throw errors to the caller.
Learnt from: Milly
PR: vim-denops/denops.vim#418
File: tests/denops/runtime/functions/plugin/check_type_test.ts:6-6
Timestamp: 2024-09-14T17:09:30.174Z
Learning: In this project, import paths prefixed with `/denops-testdata/` are defined in `deno.jsonc` via an import map, and these import paths are valid.
🧬 Code Graph Analysis (1)
tests/denops/testdata/with_import_map/plugin_with_import_map.ts (1)
tests/denops/testdata/with_import_map/helper.ts (2)
  • getMessage (3-5)
  • greeting (1-1)
🪛 Biome (1.9.4)
denops/@denops-private/plugin.ts

[error] 20-20: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🔇 Additional comments (26)
tests/denops/testdata/with_import_map/import_map.json (1)

1-7: LGTM! Standard import map structure implemented correctly.

The import map follows the standard JSON format with appropriate mappings for test scenarios. The relative path mappings and naming conventions are consistent with testing requirements.

tests/denops/testdata/with_import_map/import_map.jsonc (1)

1-10: Good addition of JSONC variant with documentation.

Having both JSON and JSONC import map files enables comprehensive testing of both formats. The comments clearly explain each mapping's purpose, improving test maintainability.

deno.jsonc (1)

16-17: Appropriate exclusion pattern for test data.

The addition follows the established pattern of excluding test data directories from Deno operations, ensuring the import map test files don't interfere with coverage or type checking.

tests/denops/testdata/with_import_map/helper.ts (1)

1-5: Simple and effective helper module for testing.

The module provides clear, testable exports that effectively demonstrate import map functionality. The implementation is clean and serves its testing purpose well.

tests/denops/testdata/with_import_map/plugin_with_import_map.ts (1)

1-13: Excellent demonstration of import map usage in Denops plugin.

The plugin correctly implements the Denops Entrypoint interface while effectively demonstrating import map functionality. The usage of imported helpers and proper async patterns align well with Denops conventions.

denops/@denops-private/service.ts (6)

1-5: LGTM! Clean refactoring to use external Plugin class.

The import changes properly introduce the external Plugin class while maintaining all necessary type imports.


41-64: Well-structured delegation to Plugin class.

The load method correctly instantiates the Plugin class and handles loading lifecycle, including proper cleanup on failure.


66-85: Proper unload delegation with resource cleanup.

The unload methods correctly delegate to the Plugin class while ensuring proper cleanup of internal state.


87-93: Clean reload implementation.

The reload method correctly preserves the script path from the unloaded plugin for reloading.


112-157: Correct delegation of dispatch calls to Plugin class.

The dispatch methods properly delegate API calls to the Plugin class while maintaining error handling and callback mechanisms.


159-174: Proper service shutdown with plugin cleanup.

The close method correctly unloads all plugins during service shutdown.

denops/@denops-private/plugin.ts (7)

25-30: Good constructor pattern with immediate loading.

The constructor properly initializes the plugin and starts the loading process immediately, which aligns with the established patterns in this codebase.


36-60: Excellent error handling with helpful user guidance.

The load method provides comprehensive error handling with specific detection and guidance for Deno module cache issues, which improves the developer experience.


62-88: Robust unload implementation with proper disposal handling.

The unload methods correctly implement idempotent behavior and handle disposal errors gracefully while maintaining event atomicity.


90-101: Excellent error handling with stack trace preservation.

The call method provides detailed error context by preferring stack traces when available, which greatly aids in debugging.


110-145: Well-designed helper functions with proper error handling.

The helper functions provide clean abstractions for script URL handling, event emission, and error detection. The emit function correctly implements the non-throwing behavior as per the codebase conventions.


147-172: Comprehensive import map detection with proper error handling.

The function correctly searches for import maps using standard Deno configuration file patterns and handles file system errors appropriately.


174-183: Clean integration of import map support with hot reloading.

The function elegantly handles both import map resolution and hot reload suffixes, providing a seamless plugin loading experience.

denops/@denops-private/plugin_test.ts (8)

1-35: Well-organized test setup with proper test data references.

The test file properly imports test utilities and references test data using the established /denops-testdata/ import map pattern.


57-72: Good test hygiene with dangling promise prevention.

The instantiation test correctly waits for the plugin to load, preventing potential test pollution from unhandled promises.


74-193: Comprehensive coverage of plugin loading scenarios.

The tests thoroughly verify event emission, error handling, and special cases like Deno cache issues, ensuring robust plugin loading behavior.


195-344: Thorough testing of unload behavior and edge cases.

The tests comprehensively cover disposal patterns, error handling, and idempotent behavior, ensuring reliable plugin unloading.


346-430: Excellent error handling test coverage.

The tests properly verify error wrapping, stack trace preservation, and handling of non-Error throws, ensuring robust API call behavior.


432-461: Proper testing of hot reload mechanism.

The test correctly verifies that the base script URL remains consistent while allowing for reload suffixes.


463-495: Critical test for system resilience.

This test ensures that plugin loading continues even when event emission fails, which is essential for system robustness.


497-570: Comprehensive validation of import map feature.

The tests thoroughly verify import map loading, usage in dispatcher calls, and graceful fallback, ensuring the new feature works correctly.

#denops: Denops;
#loadedWaiter: Promise<void>;
#unloadedWaiter?: Promise<void>;
#disposable: AsyncDisposable = voidAsyncDisposable;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix variable usage before declaration.

The static analysis tool detected that voidAsyncDisposable is used before its declaration. While JavaScript hoisting might make this work at runtime, it's better to follow proper declaration order.

Move the voidAsyncDisposable declaration before the Plugin class:

+const voidAsyncDisposable = {
+  [Symbol.asyncDispose]: () => Promise.resolve(),
+} as const satisfies AsyncDisposable;
+
 export class Plugin {
   #denops: Denops;
   #loadedWaiter: Promise<void>;
   #unloadedWaiter?: Promise<void>;
   #disposable: AsyncDisposable = voidAsyncDisposable;

And remove the duplicate declaration at lines 104-106.

🧰 Tools
🪛 Biome (1.9.4)

[error] 20-20: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🤖 Prompt for AI Agents
In denops/@denops-private/plugin.ts at line 20, the variable voidAsyncDisposable
is used before it is declared, which can cause issues despite JavaScript
hoisting. Move the declaration of voidAsyncDisposable so that it appears before
the Plugin class definition, and remove the duplicate declaration found at lines
104 to 106 to avoid redundancy.

@lambdalisue lambdalisue self-assigned this Jul 27, 2025
@lambdalisue lambdalisue marked this pull request as ready for review July 27, 2025 07:34
@lambdalisue lambdalisue merged commit 29e830d into main Jul 27, 2025
12 checks passed
@lambdalisue lambdalisue deleted the revert-447-revert-446-support-import-map branch July 27, 2025 07:38
@coderabbitai coderabbitai bot mentioned this pull request Aug 2, 2025
4 tasks
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