1515
1616Modified by Matthew Au-Yeung on 2025-07-29; see changelog.md for more details.
1717- Similar APIs ported from Java to Python.
18-
19- Changes and Current API:
20- - The API is modeled after JavaPoet's CodeBlock, but adapted for Python.
21- - CodeBlock is immutable; use the builder to create new instances.
22- - Supports formatting Java code with placeholders.
2318"""
2419
2520import re
@@ -51,7 +46,7 @@ class CodeBlock(Code["CodeBlock"]):
5146 placeholder_match = re .compile (
5247 r"""
5348 \$(
54- (?P<type1>[LSTN<>]) # $L, $S, $T, $N, $<, $>
49+ (?P<type1>[LSTN<>]) # $L, $S, $T, $N, $<, $>
5550 | # or
5651 (?P<name>[a-zA-Z_][a-zA-Z0-9_]*) # $name
5752 : # :
@@ -64,6 +59,26 @@ class CodeBlock(Code["CodeBlock"]):
6459 re .VERBOSE ,
6560 )
6661
62+ placeholder_match_with_newlines = re .compile (
63+ r"""
64+ (
65+ \$(
66+ (?P<type1>[LSTN<>]) # $L, $S, $T, $N, $<, $>
67+ | # or
68+ (?P<name>[a-zA-Z_][a-zA-Z0-9_]*) # $name
69+ : # :
70+ (?P<type2>[LSTN]) # T, L, S, N
71+ | # or
72+ (?P<index>\d+) # $1, $2, etc.
73+ (?P<type3>[LSTN<>]) # L, S, T, N, $<, $>
74+ )
75+ |
76+ (\n) # or a literal newline
77+ )
78+ """ ,
79+ re .VERBOSE ,
80+ )
81+
6782 def __init__ (self , format_parts : list [str ], args : list [Any ], named_args : dict [str , Any ]):
6883 self .format_parts = format_parts
6984 self .args = args
@@ -140,9 +155,10 @@ def emit(self, code_writer: "CodeWriter", new_line_prefix: str = "") -> None:
140155 code_writer .emit (part , new_line_prefix )
141156
142157 def emit_javadoc (self , code_writer : "CodeWriter" ) -> None :
143- code_writer .emit ("/**\n * " )
158+ code_writer .emit ("/**\n " )
144159 self .emit (code_writer , " * " )
145- code_writer .emit ("\n */" )
160+ code_writer .emit ("\n " , " * " )
161+ code_writer .emit (" */" )
146162
147163 def javadoc (self ) -> str :
148164 writer = CodeWriter ()
@@ -178,6 +194,13 @@ def join_to_code(code_blocks: list["CodeBlock"], separator: str = "") -> "CodeBl
178194
179195 @staticmethod
180196 def add_javadoc (javadoc : Optional ["CodeBlock" ], format_string : str , * args ) -> "CodeBlock" :
197+ if javadoc :
198+ return CodeBlock .join_to_code ([javadoc , CodeBlock .of (format_string , * args )])
199+ else :
200+ return CodeBlock .of (format_string , * args )
201+
202+ @staticmethod
203+ def add_javadoc_line (javadoc : Optional ["CodeBlock" ], format_string : str , * args ) -> "CodeBlock" :
181204 if javadoc :
182205 return CodeBlock .join_to_code ([javadoc , CodeBlock .of (format_string , * args )], "\n " )
183206 else :
@@ -207,7 +230,7 @@ def __init__(
207230
208231 def add (self , format_string : str , * args , ** kwargs ) -> "CodeBlock.Builder" :
209232 # Check for arguments in the format string
210- matches = list (re .finditer (CodeBlock .placeholder_match , format_string ))
233+ matches = list (re .finditer (CodeBlock .placeholder_match_with_newlines , format_string ))
211234
212235 # Simple case: no arguments
213236 if not matches :
@@ -248,6 +271,11 @@ def add_statement(self, format_string: str, *args, **kwargs) -> "CodeBlock.Build
248271 self .add (format_string , * args , ** kwargs )
249272 self .add (";\n " )
250273 return self
274+
275+ def add_line (self , format_string : str , * args , ** kwargs ) -> "CodeBlock.Builder" :
276+ self .add (format_string , * args , ** kwargs )
277+ self .add ("\n " )
278+ return self
251279
252280 def begin_statement (self , format_string : str , * args , ** kwargs ) -> "CodeBlock.Builder" :
253281 parts = format_string .split ("\n " )
0 commit comments