Skip to content

perf: improve TS code generation performance #2082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 14, 2025
Merged

perf: improve TS code generation performance #2082

merged 1 commit into from
Apr 14, 2025

Conversation

ymc9
Copy link
Member

@ymc9 ymc9 commented Apr 14, 2025

No description provided.

Copy link
Contributor

coderabbitai bot commented Apr 14, 2025

📝 Walkthrough

Walkthrough

The changes refactor code generation modules by replacing the use of CodeBlockWriter with a new abstraction, CodeWriter, and its implementation in the FastWriter class. Multiple functions and methods across policy-related and model metadata generation files have had their signatures streamlined by removing the SourceFile parameter and simplifying parameter types. Additionally, an extraFunctions array is introduced in some generators to collect function declarations. Overall, these modifications standardize and improve the code writing process without altering core business logic.

Changes

File(s) Change Summary
packages/schema/src/plugins/enhancer/policy/expression-writer.ts Updated the constructor of ExpressionWriter: changed the writer parameter type from CodeBlockWriter to CodeWriter.
packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts Refactored multiple methods in PolicyGenerator: replaced CodeBlockWriter with CodeWriter, removed the sourceFile parameter from several functions, and added a new private member extraFunctions to store generated function declarations.
packages/schema/src/plugins/enhancer/policy/utils.ts Updated functions (generateConstantQueryGuardFunction, generateQueryGuardFunction, and generateEntityCheckerFunction): removed the sourceFile parameter, replaced WriterFunction usage with simple string arrays, and simplified function structure.
packages/sdk/src/code-gen.ts Introduced a new interface CodeWriter and the class FastWriter that implements it, providing methods (block, inlineBlock, write, writeLine, and conditionalWrite) for structured code generation.
packages/sdk/src/model-meta-generator.ts Updated several functions (e.g., generateModelMetadata, writeModels, writeTypeDefs, etc.) by replacing CodeBlockWriter with CodeWriter, removing sourceFile parameters, and adding an extraFunctions parameter to collect additional function declarations during metadata generation.

Sequence Diagram(s)

sequenceDiagram
    participant PG as PolicyGenerator
    participant FW as FastWriter (CodeWriter)
    participant EF as ExtraFunctions
    participant SF as SourceFile

    PG->>FW: Initialize code writer instance
    PG->>FW: Write policy definitions (writePolicy, etc.)
    PG->>EF: Collect extra function declarations
    PG->>SF: Append extra functions to policy content
    SF-->>PG: Return final policy file
Loading
sequenceDiagram
    participant MM as ModelMetaGenerator
    participant FW as FastWriter (CodeWriter)
    participant EF as ExtraFunctions
    participant SF as SourceFile

    MM->>FW: Initialize code writer instance
    MM->>FW: Write models, type definitions, and fields
    MM->>EF: Collect additional function declarations
    MM->>SF: Merge metadata with extra functions
    SF-->>MM: Return final metadata output
Loading

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

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:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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 resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts (1)

240-243: Consider extracting common writer patterns.

The pattern of creating a new FastWriter, writing conditionally, and then extracting the result is repeated several times in the file. Consider extracting this into a utility function to reduce duplication.

+private generateStatementFromCondition(condition: boolean, trueBlock: () => void, falseBlock: () => void): string {
+    const writer = new FastWriter();
+    if (condition) {
+        trueBlock();
+    } else {
+        falseBlock();
+    }
+    return writer.result;
+}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6a7ef93 and 8bd694a.

📒 Files selected for processing (5)
  • packages/schema/src/plugins/enhancer/policy/expression-writer.ts (2 hunks)
  • packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts (24 hunks)
  • packages/schema/src/plugins/enhancer/policy/utils.ts (9 hunks)
  • packages/sdk/src/code-gen.ts (1 hunks)
  • packages/sdk/src/model-meta-generator.ts (14 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
packages/schema/src/plugins/enhancer/policy/expression-writer.ts (1)
packages/sdk/src/code-gen.ts (1)
  • CodeWriter (77-83)
packages/sdk/src/model-meta-generator.ts (3)
packages/sdk/src/code-gen.ts (2)
  • FastWriter (88-129)
  • CodeWriter (77-83)
packages/language/src/ast.ts (1)
  • DataModel (56-66)
packages/sdk/src/utils.ts (1)
  • getAuthDecl (482-488)
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: build-test (20.x)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: build-test (20.x)
  • GitHub Check: build-test (20.x)
  • GitHub Check: OSSAR-Scan
🔇 Additional comments (33)
packages/schema/src/plugins/enhancer/policy/expression-writer.ts (2)

24-25: Update import to use CodeWriter from SDK

The import has been updated to use CodeWriter from '@zenstackhq/sdk' instead of (presumably) the previously used CodeBlockWriter. This aligns with the new code generation abstraction introduced in this PR.


80-80: Constructor parameter type updated to CodeWriter

The constructor parameter type has been changed from CodeBlockWriter to CodeWriter. This is consistent with the overall refactoring across multiple files to improve code generation performance.

packages/sdk/src/code-gen.ts (2)

73-83: Good abstraction for source code generation

The CodeWriter interface provides a clean abstraction for code generation with methods for block creation, text writing, and conditional logic. This interface will make it easier to swap out different implementations in the future.


88-129: Efficient FastWriter implementation

The FastWriter class implements the CodeWriter interface with a straightforward string-based approach that should be more efficient than the previous implementation. The class maintains internal state for indentation and provides methods that correspond to the interface requirements.

Key improvements:

  • Uses direct string concatenation for better performance
  • Simple indentation management
  • Clean API with the result getter to retrieve generated code
packages/schema/src/plugins/enhancer/policy/utils.ts (5)

4-6: Import FastWriter from SDK

The import of FastWriter from '@zenstackhq/sdk' has been added, which is used in the refactored functions below.


43-43: Update ts-morph imports for function structure

The import has been updated to include FunctionDeclarationStructure and OptionalKind from ts-morph. This supports the new approach of returning structured function definitions rather than directly writing to source files.


269-286: Refactor to return function structure instead of writing directly

The generateConstantQueryGuardFunction now returns a FunctionDeclarationStructure object instead of writing directly to a source file. This is a better separation of concerns that allows for more flexibility in how the function declarations are used.


291-366: Improved code generation with FastWriter

The function has been refactored to use FastWriter and return a FunctionDeclarationStructure. Key improvements:

  1. No longer requires a SourceFile parameter, simplifying the API
  2. Uses FastWriter for generating code blocks
  3. More structured approach with cleaner conditionals for generating code

This change maintains the same functionality while making the code more efficient and maintainable.


433-497: Refactor entity checker function to return structure

Similar to the previous functions, generateEntityCheckerFunction has been updated to return a FunctionDeclarationStructure instead of writing directly to a source file. This continues the pattern of separating the structure definition from the actual writing process.

packages/sdk/src/model-meta-generator.ts (6)

22-27: Update imports for new code generation approach

The imports have been updated to include FastWriter and related structures from ts-morph, supporting the new code generation approach throughout the file.


77-91: Refactor generate function to use FastWriter

The generate function has been improved to:

  1. Use FastWriter for code generation
  2. Collect extra functions in an array
  3. Add these functions to the source file if present

This change makes the code more structured and maintains a clear separation between code generation and source file manipulation.


101-107: Update function signature to use CodeWriter

The generateModelMetadata function signature has been updated to use CodeWriter instead of SourceFile and CodeBlockWriter, and to include an extraFunctions parameter. This simplifies the function and follows the pattern established in other files.


117-122: Simplify writeModels function signature

The writeModels function no longer requires a SourceFile parameter and now accepts a CodeWriter and extraFunctions array. This is consistent with the overall refactoring approach.


233-237: Simplify writeFields function signature

The writeFields function now uses CodeWriter instead of SourceFile and CodeBlockWriter, and includes an extraFunctions parameter. This continues the pattern of simplification across the codebase.


509-544: Refactor generateDefaultValueProvider to use extraFunctions array

The generateDefaultValueProvider function has been updated to:

  1. No longer require a SourceFile parameter
  2. Accept an extraFunctions array
  3. Push generated functions to this array instead of directly to the source file

This change improves the function's cohesion by focusing it on generating the function structure rather than modifying the source file.

packages/schema/src/plugins/enhancer/policy/policy-guard-generator.ts (18)

18-20: Good implementation of the new abstraction.

The switch from directly using CodeBlockWriter to the more abstract CodeWriter interface with a concrete FastWriter implementation supports better separation of concerns and is consistent with the PR's performance improvement goals.


37-37: Clean import update.

Updated the import to include OptionalKind which is needed for the new extraFunctions array.


54-55: Good design for function declaration management.

Adding the extraFunctions array is a clean approach to collect function declarations first and add them to the source file later, which improves code organization.


65-70: Improved code generation approach.

Using FastWriter instead of directly writing to the source file centralizes code generation and provides better control over the output.


78-78: Simplified variable initialization.

Directly using writer.result for the initializer eliminates unnecessary intermediate variables.


83-85: Clean separation of concerns.

Adding the conditional check for extra functions provides a clean separation between function collection and function insertion into the source file.


126-126: Consistent method signature simplification.

Simplified method signatures by replacing CodeBlockWriter with CodeWriter and removing the sourceFile parameter, making the code more consistent and less coupled.

Also applies to: 148-150, 163-164, 172-173, 184-185, 292-293, 302-303, 323-324, 540-540, 549-549, 610-610


187-188: Improved function name handling.

Now gets the function name from the generation method rather than generating and immediately using the function, which is more maintainable.


232-271: Effective refactoring of code generation.

The generateCreateInputCheckerFunction now uses a FastWriter for statement generation and pushes to extraFunctions instead of immediately creating function structures. This approach is more consistent with the overall design pattern in the PR.


273-290: Clean function declaration management.

Returning just the function name and storing the function structure in extraFunctions simplifies the API and makes function management more centralized.


400-417: Improved return value structure.

The writeEntityChecker method now returns a structured object with functionName and selector, which provides better data organization and makes the API more explicit.


433-440: Consistent function handling.

Now consistently adds generated functions to extraFunctions array and references them by name, which aligns with the pattern used throughout the file.


465-467: Standardized function generation pattern.

Follows the standard pattern of generating a function, adding it to extraFunctions, and writing the function name to the output.


500-501: Consistent approach to permission checker functions.

Uses the same pattern of getting the function name and writing it, maintaining consistency with other similar method implementations.


520-533: Effective function declaration refactoring.

Changed function declaration to return just the name, with the structure pushed to extraFunctions, maintaining consistency with other function generation methods.


565-567: Consistent pattern application across file.

Maintains consistency in how guard functions are generated, stored, and referenced throughout the file.

Also applies to: 626-628, 649-650


674-679: Clean method refactoring.

Simplified the writeAuthSelector method by removing the sourceFile parameter while maintaining the core functionality.


722-741: Consistent pattern application.

The writeValidationMeta method follows the same pattern of accepting a CodeWriter parameter and using it consistently.

@ymc9 ymc9 merged commit d8f95e5 into dev Apr 14, 2025
11 checks passed
@ymc9 ymc9 deleted the perf/code-gen-speed branch April 14, 2025 00:41
@ymc9
Copy link
Member Author

ymc9 commented Apr 14, 2025

fixes #2058

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