Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/sphinx/domains/c/_ast.py: 3%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1260 statements  

1from __future__ import annotations 

2 

3import sys 

4import warnings 

5from typing import TYPE_CHECKING, Any, Union, cast 

6 

7from docutils import nodes 

8 

9from sphinx import addnodes 

10from sphinx.domains.c._ids import _id_prefix, _max_id 

11from sphinx.util.cfamily import ( 

12 ASTAttributeList, 

13 ASTBaseBase, 

14 ASTBaseParenExprList, 

15 StringifyTransform, 

16 UnsupportedMultiCharacterCharLiteral, 

17 verify_description_mode, 

18) 

19 

20if TYPE_CHECKING: 

21 

22 from docutils.nodes import Element, Node, TextElement 

23 

24 from sphinx.domains.c._symbol import Symbol 

25 from sphinx.environment import BuildEnvironment 

26 

27DeclarationType = Union[ 

28 "ASTStruct", "ASTUnion", "ASTEnum", "ASTEnumerator", 

29 "ASTType", "ASTTypeWithInit", "ASTMacro", 

30] 

31 

32 

33class ASTBase(ASTBaseBase): 

34 def describe_signature(self, signode: TextElement, mode: str, 

35 env: BuildEnvironment, symbol: Symbol) -> None: 

36 raise NotImplementedError(repr(self)) 

37 

38 

39# Names 

40################################################################################ 

41 

42class ASTIdentifier(ASTBaseBase): 

43 def __init__(self, name: str) -> None: 

44 if not isinstance(name, str) or len(name) == 0: 

45 raise AssertionError 

46 self.name = sys.intern(name) 

47 self.is_anonymous = name[0] == '@' 

48 

49 # ASTBaseBase already implements this method, 

50 # but specialising it here improves performance 

51 def __eq__(self, other: object) -> bool: 

52 if not isinstance(other, ASTIdentifier): 

53 return NotImplemented 

54 return self.name == other.name 

55 

56 def is_anon(self) -> bool: 

57 return self.is_anonymous 

58 

59 # and this is where we finally make a difference between __str__ and the display string 

60 

61 def __str__(self) -> str: 

62 return self.name 

63 

64 def get_display_string(self) -> str: 

65 return "[anonymous]" if self.is_anonymous else self.name 

66 

67 def describe_signature(self, signode: TextElement, mode: str, env: BuildEnvironment, 

68 prefix: str, symbol: Symbol) -> None: 

69 # note: slightly different signature of describe_signature due to the prefix 

70 verify_description_mode(mode) 

71 if self.is_anonymous: 

72 node = addnodes.desc_sig_name(text="[anonymous]") 

73 else: 

74 node = addnodes.desc_sig_name(self.name, self.name) 

75 if mode == 'markType': 

76 targetText = prefix + self.name 

77 pnode = addnodes.pending_xref('', refdomain='c', 

78 reftype='identifier', 

79 reftarget=targetText, modname=None, 

80 classname=None) 

81 pnode['c:parent_key'] = symbol.get_lookup_key() 

82 pnode += node 

83 signode += pnode 

84 elif mode == 'lastIsName': 

85 nameNode = addnodes.desc_name() 

86 nameNode += node 

87 signode += nameNode 

88 elif mode == 'noneIsName': 

89 signode += node 

90 else: 

91 raise Exception('Unknown description mode: %s' % mode) 

92 

93 @property 

94 def identifier(self) -> str: 

95 warnings.warn( 

96 '`ASTIdentifier.identifier` is deprecated, use `ASTIdentifier.name` instead', 

97 DeprecationWarning, stacklevel=2, 

98 ) 

99 return self.name 

100 

101 

102class ASTNestedName(ASTBase): 

103 def __init__(self, names: list[ASTIdentifier], rooted: bool) -> None: 

104 assert len(names) > 0 

105 self.names = names 

106 self.rooted = rooted 

107 

108 def __eq__(self, other: object) -> bool: 

109 if not isinstance(other, ASTNestedName): 

110 return NotImplemented 

111 return self.names == other.names and self.rooted == other.rooted 

112 

113 def __hash__(self) -> int: 

114 return hash((self.names, self.rooted)) 

115 

116 @property 

117 def name(self) -> ASTNestedName: 

118 return self 

119 

120 def get_id(self, version: int) -> str: 

121 return '.'.join(str(n) for n in self.names) 

122 

123 def _stringify(self, transform: StringifyTransform) -> str: 

124 res = '.'.join(transform(n) for n in self.names) 

125 if self.rooted: 

126 return '.' + res 

127 else: 

128 return res 

129 

130 def describe_signature(self, signode: TextElement, mode: str, 

131 env: BuildEnvironment, symbol: Symbol) -> None: 

132 verify_description_mode(mode) 

133 # just print the name part, with template args, not template params 

134 if mode == 'noneIsName': 

135 if self.rooted: 

136 unreachable = "Can this happen?" 

137 raise AssertionError(unreachable) # TODO 

138 signode += nodes.Text('.') 

139 for i in range(len(self.names)): 

140 if i != 0: 

141 unreachable = "Can this happen?" 

142 raise AssertionError(unreachable) # TODO 

143 signode += nodes.Text('.') 

144 n = self.names[i] 

145 n.describe_signature(signode, mode, env, '', symbol) 

146 elif mode == 'param': 

147 assert not self.rooted, str(self) 

148 assert len(self.names) == 1 

149 self.names[0].describe_signature(signode, 'noneIsName', env, '', symbol) 

150 elif mode in ('markType', 'lastIsName', 'markName'): 

151 # Each element should be a pending xref targeting the complete 

152 # prefix. 

153 prefix = '' 

154 first = True 

155 names = self.names[:-1] if mode == 'lastIsName' else self.names 

156 # If lastIsName, then wrap all of the prefix in a desc_addname, 

157 # else append directly to signode. 

158 # TODO: also for C? 

159 # NOTE: Breathe previously relied on the prefix being in the desc_addname node, 

160 # so it can remove it in inner declarations. 

161 dest = signode 

162 if mode == 'lastIsName': 

163 dest = addnodes.desc_addname() 

164 if self.rooted: 

165 prefix += '.' 

166 if mode == 'lastIsName' and len(names) == 0: 

167 signode += addnodes.desc_sig_punctuation('.', '.') 

168 else: 

169 dest += addnodes.desc_sig_punctuation('.', '.') 

170 for i in range(len(names)): 

171 ident = names[i] 

172 if not first: 

173 dest += addnodes.desc_sig_punctuation('.', '.') 

174 prefix += '.' 

175 first = False 

176 txt_ident = str(ident) 

177 if txt_ident != '': 

178 ident.describe_signature(dest, 'markType', env, prefix, symbol) 

179 prefix += txt_ident 

180 if mode == 'lastIsName': 

181 if len(self.names) > 1: 

182 dest += addnodes.desc_sig_punctuation('.', '.') 

183 signode += dest 

184 self.names[-1].describe_signature(signode, mode, env, '', symbol) 

185 else: 

186 raise Exception('Unknown description mode: %s' % mode) 

187 

188 

189################################################################################ 

190# Expressions 

191################################################################################ 

192 

193class ASTExpression(ASTBase): 

194 pass 

195 

196 

197# Primary expressions 

198################################################################################ 

199 

200class ASTLiteral(ASTExpression): 

201 pass 

202 

203 

204class ASTBooleanLiteral(ASTLiteral): 

205 def __init__(self, value: bool) -> None: 

206 self.value = value 

207 

208 def __eq__(self, other: object) -> bool: 

209 if not isinstance(other, ASTBooleanLiteral): 

210 return NotImplemented 

211 return self.value == other.value 

212 

213 def __hash__(self) -> int: 

214 return hash(self.value) 

215 

216 def _stringify(self, transform: StringifyTransform) -> str: 

217 if self.value: 

218 return 'true' 

219 else: 

220 return 'false' 

221 

222 def describe_signature(self, signode: TextElement, mode: str, 

223 env: BuildEnvironment, symbol: Symbol) -> None: 

224 txt = str(self) 

225 signode += addnodes.desc_sig_keyword(txt, txt) 

226 

227 

228class ASTNumberLiteral(ASTLiteral): 

229 def __init__(self, data: str) -> None: 

230 self.data = data 

231 

232 def __eq__(self, other: object) -> bool: 

233 if not isinstance(other, ASTNumberLiteral): 

234 return NotImplemented 

235 return self.data == other.data 

236 

237 def __hash__(self) -> int: 

238 return hash(self.data) 

239 

240 def _stringify(self, transform: StringifyTransform) -> str: 

241 return self.data 

242 

243 def describe_signature(self, signode: TextElement, mode: str, 

244 env: BuildEnvironment, symbol: Symbol) -> None: 

245 txt = str(self) 

246 signode += addnodes.desc_sig_literal_number(txt, txt) 

247 

248 

249class ASTCharLiteral(ASTLiteral): 

250 def __init__(self, prefix: str, data: str) -> None: 

251 self.prefix = prefix # may be None when no prefix 

252 self.data = data 

253 decoded = data.encode().decode('unicode-escape') 

254 if len(decoded) == 1: 

255 self.value = ord(decoded) 

256 else: 

257 raise UnsupportedMultiCharacterCharLiteral(decoded) 

258 

259 def __eq__(self, other: object) -> bool: 

260 if not isinstance(other, ASTCharLiteral): 

261 return NotImplemented 

262 return ( 

263 self.prefix == other.prefix 

264 and self.value == other.value 

265 ) 

266 

267 def __hash__(self) -> int: 

268 return hash((self.prefix, self.value)) 

269 

270 def _stringify(self, transform: StringifyTransform) -> str: 

271 if self.prefix is None: 

272 return "'" + self.data + "'" 

273 else: 

274 return self.prefix + "'" + self.data + "'" 

275 

276 def describe_signature(self, signode: TextElement, mode: str, 

277 env: BuildEnvironment, symbol: Symbol) -> None: 

278 txt = str(self) 

279 signode += addnodes.desc_sig_literal_char(txt, txt) 

280 

281 

282class ASTStringLiteral(ASTLiteral): 

283 def __init__(self, data: str) -> None: 

284 self.data = data 

285 

286 def __eq__(self, other: object) -> bool: 

287 if not isinstance(other, ASTStringLiteral): 

288 return NotImplemented 

289 return self.data == other.data 

290 

291 def __hash__(self) -> int: 

292 return hash(self.data) 

293 

294 def _stringify(self, transform: StringifyTransform) -> str: 

295 return self.data 

296 

297 def describe_signature(self, signode: TextElement, mode: str, 

298 env: BuildEnvironment, symbol: Symbol) -> None: 

299 txt = str(self) 

300 signode += addnodes.desc_sig_literal_string(txt, txt) 

301 

302 

303class ASTIdExpression(ASTExpression): 

304 def __init__(self, name: ASTNestedName) -> None: 

305 # note: this class is basically to cast a nested name as an expression 

306 self.name = name 

307 

308 def __eq__(self, other: object) -> bool: 

309 if not isinstance(other, ASTIdExpression): 

310 return NotImplemented 

311 return self.name == other.name 

312 

313 def __hash__(self) -> int: 

314 return hash(self.name) 

315 

316 def _stringify(self, transform: StringifyTransform) -> str: 

317 return transform(self.name) 

318 

319 def get_id(self, version: int) -> str: 

320 return self.name.get_id(version) 

321 

322 def describe_signature(self, signode: TextElement, mode: str, 

323 env: BuildEnvironment, symbol: Symbol) -> None: 

324 self.name.describe_signature(signode, mode, env, symbol) 

325 

326 

327class ASTParenExpr(ASTExpression): 

328 def __init__(self, expr: ASTExpression) -> None: 

329 self.expr = expr 

330 

331 def __eq__(self, other: object) -> bool: 

332 if not isinstance(other, ASTParenExpr): 

333 return NotImplemented 

334 return self.expr == other.expr 

335 

336 def __hash__(self) -> int: 

337 return hash(self.expr) 

338 

339 def _stringify(self, transform: StringifyTransform) -> str: 

340 return '(' + transform(self.expr) + ')' 

341 

342 def get_id(self, version: int) -> str: 

343 return self.expr.get_id(version) # type: ignore[attr-defined] 

344 

345 def describe_signature(self, signode: TextElement, mode: str, 

346 env: BuildEnvironment, symbol: Symbol) -> None: 

347 signode += addnodes.desc_sig_punctuation('(', '(') 

348 self.expr.describe_signature(signode, mode, env, symbol) 

349 signode += addnodes.desc_sig_punctuation(')', ')') 

350 

351 

352# Postfix expressions 

353################################################################################ 

354 

355class ASTPostfixOp(ASTBase): 

356 pass 

357 

358 

359class ASTPostfixCallExpr(ASTPostfixOp): 

360 def __init__(self, lst: ASTParenExprList | ASTBracedInitList) -> None: 

361 self.lst = lst 

362 

363 def __eq__(self, other: object) -> bool: 

364 if not isinstance(other, ASTPostfixCallExpr): 

365 return NotImplemented 

366 return self.lst == other.lst 

367 

368 def __hash__(self) -> int: 

369 return hash(self.lst) 

370 

371 def _stringify(self, transform: StringifyTransform) -> str: 

372 return transform(self.lst) 

373 

374 def describe_signature(self, signode: TextElement, mode: str, 

375 env: BuildEnvironment, symbol: Symbol) -> None: 

376 self.lst.describe_signature(signode, mode, env, symbol) 

377 

378 

379class ASTPostfixArray(ASTPostfixOp): 

380 def __init__(self, expr: ASTExpression) -> None: 

381 self.expr = expr 

382 

383 def __eq__(self, other: object) -> bool: 

384 if not isinstance(other, ASTPostfixArray): 

385 return NotImplemented 

386 return self.expr == other.expr 

387 

388 def __hash__(self) -> int: 

389 return hash(self.expr) 

390 

391 def _stringify(self, transform: StringifyTransform) -> str: 

392 return '[' + transform(self.expr) + ']' 

393 

394 def describe_signature(self, signode: TextElement, mode: str, 

395 env: BuildEnvironment, symbol: Symbol) -> None: 

396 signode += addnodes.desc_sig_punctuation('[', '[') 

397 self.expr.describe_signature(signode, mode, env, symbol) 

398 signode += addnodes.desc_sig_punctuation(']', ']') 

399 

400 

401class ASTPostfixInc(ASTPostfixOp): 

402 def _stringify(self, transform: StringifyTransform) -> str: 

403 return '++' 

404 

405 def describe_signature(self, signode: TextElement, mode: str, 

406 env: BuildEnvironment, symbol: Symbol) -> None: 

407 signode += addnodes.desc_sig_operator('++', '++') 

408 

409 

410class ASTPostfixDec(ASTPostfixOp): 

411 def _stringify(self, transform: StringifyTransform) -> str: 

412 return '--' 

413 

414 def describe_signature(self, signode: TextElement, mode: str, 

415 env: BuildEnvironment, symbol: Symbol) -> None: 

416 signode += addnodes.desc_sig_operator('--', '--') 

417 

418 

419class ASTPostfixMemberOfPointer(ASTPostfixOp): 

420 def __init__(self, name: ASTNestedName) -> None: 

421 self.name = name 

422 

423 def __eq__(self, other: object) -> bool: 

424 if not isinstance(other, ASTPostfixMemberOfPointer): 

425 return NotImplemented 

426 return self.name == other.name 

427 

428 def __hash__(self) -> int: 

429 return hash(self.name) 

430 

431 def _stringify(self, transform: StringifyTransform) -> str: 

432 return '->' + transform(self.name) 

433 

434 def describe_signature(self, signode: TextElement, mode: str, 

435 env: BuildEnvironment, symbol: Symbol) -> None: 

436 signode += addnodes.desc_sig_operator('->', '->') 

437 self.name.describe_signature(signode, 'noneIsName', env, symbol) 

438 

439 

440class ASTPostfixExpr(ASTExpression): 

441 def __init__(self, prefix: ASTExpression, postFixes: list[ASTPostfixOp]) -> None: 

442 self.prefix = prefix 

443 self.postFixes = postFixes 

444 

445 def __eq__(self, other: object) -> bool: 

446 if not isinstance(other, ASTPostfixExpr): 

447 return NotImplemented 

448 return self.prefix == other.prefix and self.postFixes == other.postFixes 

449 

450 def __hash__(self) -> int: 

451 return hash((self.prefix, self.postFixes)) 

452 

453 def _stringify(self, transform: StringifyTransform) -> str: 

454 return ''.join([transform(self.prefix), *(transform(p) for p in self.postFixes)]) 

455 

456 def describe_signature(self, signode: TextElement, mode: str, 

457 env: BuildEnvironment, symbol: Symbol) -> None: 

458 self.prefix.describe_signature(signode, mode, env, symbol) 

459 for p in self.postFixes: 

460 p.describe_signature(signode, mode, env, symbol) 

461 

462 

463# Unary expressions 

464################################################################################ 

465 

466class ASTUnaryOpExpr(ASTExpression): 

467 def __init__(self, op: str, expr: ASTExpression) -> None: 

468 self.op = op 

469 self.expr = expr 

470 

471 def __eq__(self, other: object) -> bool: 

472 if not isinstance(other, ASTUnaryOpExpr): 

473 return NotImplemented 

474 return self.op == other.op and self.expr == other.expr 

475 

476 def __hash__(self) -> int: 

477 return hash((self.op, self.expr)) 

478 

479 def _stringify(self, transform: StringifyTransform) -> str: 

480 if self.op[0] in 'cn': 

481 return self.op + " " + transform(self.expr) 

482 else: 

483 return self.op + transform(self.expr) 

484 

485 def describe_signature(self, signode: TextElement, mode: str, 

486 env: BuildEnvironment, symbol: Symbol) -> None: 

487 if self.op[0] in 'cn': 

488 signode += addnodes.desc_sig_keyword(self.op, self.op) 

489 signode += addnodes.desc_sig_space() 

490 else: 

491 signode += addnodes.desc_sig_operator(self.op, self.op) 

492 self.expr.describe_signature(signode, mode, env, symbol) 

493 

494 

495class ASTSizeofType(ASTExpression): 

496 def __init__(self, typ: ASTType) -> None: 

497 self.typ = typ 

498 

499 def __eq__(self, other: object) -> bool: 

500 if not isinstance(other, ASTSizeofType): 

501 return NotImplemented 

502 return self.typ == other.typ 

503 

504 def __hash__(self) -> int: 

505 return hash(self.typ) 

506 

507 def _stringify(self, transform: StringifyTransform) -> str: 

508 return "sizeof(" + transform(self.typ) + ")" 

509 

510 def describe_signature(self, signode: TextElement, mode: str, 

511 env: BuildEnvironment, symbol: Symbol) -> None: 

512 signode += addnodes.desc_sig_keyword('sizeof', 'sizeof') 

513 signode += addnodes.desc_sig_punctuation('(', '(') 

514 self.typ.describe_signature(signode, mode, env, symbol) 

515 signode += addnodes.desc_sig_punctuation(')', ')') 

516 

517 

518class ASTSizeofExpr(ASTExpression): 

519 def __init__(self, expr: ASTExpression) -> None: 

520 self.expr = expr 

521 

522 def __eq__(self, other: object) -> bool: 

523 if not isinstance(other, ASTSizeofExpr): 

524 return NotImplemented 

525 return self.expr == other.expr 

526 

527 def __hash__(self) -> int: 

528 return hash(self.expr) 

529 

530 def _stringify(self, transform: StringifyTransform) -> str: 

531 return "sizeof " + transform(self.expr) 

532 

533 def describe_signature(self, signode: TextElement, mode: str, 

534 env: BuildEnvironment, symbol: Symbol) -> None: 

535 signode += addnodes.desc_sig_keyword('sizeof', 'sizeof') 

536 signode += addnodes.desc_sig_space() 

537 self.expr.describe_signature(signode, mode, env, symbol) 

538 

539 

540class ASTAlignofExpr(ASTExpression): 

541 def __init__(self, typ: ASTType) -> None: 

542 self.typ = typ 

543 

544 def __eq__(self, other: object) -> bool: 

545 if not isinstance(other, ASTAlignofExpr): 

546 return NotImplemented 

547 return self.typ == other.typ 

548 

549 def __hash__(self) -> int: 

550 return hash(self.typ) 

551 

552 def _stringify(self, transform: StringifyTransform) -> str: 

553 return "alignof(" + transform(self.typ) + ")" 

554 

555 def describe_signature(self, signode: TextElement, mode: str, 

556 env: BuildEnvironment, symbol: Symbol) -> None: 

557 signode += addnodes.desc_sig_keyword('alignof', 'alignof') 

558 signode += addnodes.desc_sig_punctuation('(', '(') 

559 self.typ.describe_signature(signode, mode, env, symbol) 

560 signode += addnodes.desc_sig_punctuation(')', ')') 

561 

562 

563# Other expressions 

564################################################################################ 

565 

566class ASTCastExpr(ASTExpression): 

567 def __init__(self, typ: ASTType, expr: ASTExpression) -> None: 

568 self.typ = typ 

569 self.expr = expr 

570 

571 def __eq__(self, other: object) -> bool: 

572 if not isinstance(other, ASTCastExpr): 

573 return NotImplemented 

574 return ( 

575 self.typ == other.typ 

576 and self.expr == other.expr 

577 ) 

578 

579 def __hash__(self) -> int: 

580 return hash((self.typ, self.expr)) 

581 

582 def _stringify(self, transform: StringifyTransform) -> str: 

583 res = ['('] 

584 res.append(transform(self.typ)) 

585 res.append(')') 

586 res.append(transform(self.expr)) 

587 return ''.join(res) 

588 

589 def describe_signature(self, signode: TextElement, mode: str, 

590 env: BuildEnvironment, symbol: Symbol) -> None: 

591 signode += addnodes.desc_sig_punctuation('(', '(') 

592 self.typ.describe_signature(signode, mode, env, symbol) 

593 signode += addnodes.desc_sig_punctuation(')', ')') 

594 self.expr.describe_signature(signode, mode, env, symbol) 

595 

596 

597class ASTBinOpExpr(ASTBase): 

598 def __init__(self, exprs: list[ASTExpression], ops: list[str]) -> None: 

599 assert len(exprs) > 0 

600 assert len(exprs) == len(ops) + 1 

601 self.exprs = exprs 

602 self.ops = ops 

603 

604 def __eq__(self, other: object) -> bool: 

605 if not isinstance(other, ASTBinOpExpr): 

606 return NotImplemented 

607 return ( 

608 self.exprs == other.exprs 

609 and self.ops == other.ops 

610 ) 

611 

612 def __hash__(self) -> int: 

613 return hash((self.exprs, self.ops)) 

614 

615 def _stringify(self, transform: StringifyTransform) -> str: 

616 res = [] 

617 res.append(transform(self.exprs[0])) 

618 for i in range(1, len(self.exprs)): 

619 res.append(' ') 

620 res.append(self.ops[i - 1]) 

621 res.append(' ') 

622 res.append(transform(self.exprs[i])) 

623 return ''.join(res) 

624 

625 def describe_signature(self, signode: TextElement, mode: str, 

626 env: BuildEnvironment, symbol: Symbol) -> None: 

627 self.exprs[0].describe_signature(signode, mode, env, symbol) 

628 for i in range(1, len(self.exprs)): 

629 signode += addnodes.desc_sig_space() 

630 op = self.ops[i - 1] 

631 if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'): 

632 signode += addnodes.desc_sig_keyword(op, op) 

633 else: 

634 signode += addnodes.desc_sig_operator(op, op) 

635 signode += addnodes.desc_sig_space() 

636 self.exprs[i].describe_signature(signode, mode, env, symbol) 

637 

638 

639class ASTAssignmentExpr(ASTExpression): 

640 def __init__(self, exprs: list[ASTExpression], ops: list[str]) -> None: 

641 assert len(exprs) > 0 

642 assert len(exprs) == len(ops) + 1 

643 self.exprs = exprs 

644 self.ops = ops 

645 

646 def __eq__(self, other: object) -> bool: 

647 if not isinstance(other, ASTAssignmentExpr): 

648 return NotImplemented 

649 return ( 

650 self.exprs == other.exprs 

651 and self.ops == other.ops 

652 ) 

653 

654 def __hash__(self) -> int: 

655 return hash((self.exprs, self.ops)) 

656 

657 def _stringify(self, transform: StringifyTransform) -> str: 

658 res = [] 

659 res.append(transform(self.exprs[0])) 

660 for i in range(1, len(self.exprs)): 

661 res.append(' ') 

662 res.append(self.ops[i - 1]) 

663 res.append(' ') 

664 res.append(transform(self.exprs[i])) 

665 return ''.join(res) 

666 

667 def describe_signature(self, signode: TextElement, mode: str, 

668 env: BuildEnvironment, symbol: Symbol) -> None: 

669 self.exprs[0].describe_signature(signode, mode, env, symbol) 

670 for i in range(1, len(self.exprs)): 

671 signode += addnodes.desc_sig_space() 

672 op = self.ops[i - 1] 

673 if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'): 

674 signode += addnodes.desc_sig_keyword(op, op) 

675 else: 

676 signode += addnodes.desc_sig_operator(op, op) 

677 signode += addnodes.desc_sig_space() 

678 self.exprs[i].describe_signature(signode, mode, env, symbol) 

679 

680 

681class ASTFallbackExpr(ASTExpression): 

682 def __init__(self, expr: str) -> None: 

683 self.expr = expr 

684 

685 def __eq__(self, other: object) -> bool: 

686 if not isinstance(other, ASTFallbackExpr): 

687 return NotImplemented 

688 return self.expr == other.expr 

689 

690 def __hash__(self) -> int: 

691 return hash(self.expr) 

692 

693 def _stringify(self, transform: StringifyTransform) -> str: 

694 return self.expr 

695 

696 def get_id(self, version: int) -> str: 

697 return str(self.expr) 

698 

699 def describe_signature(self, signode: TextElement, mode: str, 

700 env: BuildEnvironment, symbol: Symbol) -> None: 

701 signode += nodes.literal(self.expr, self.expr) 

702 

703 

704################################################################################ 

705# Types 

706################################################################################ 

707 

708class ASTTrailingTypeSpec(ASTBase): 

709 pass 

710 

711 

712class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec): 

713 def __init__(self, names: list[str]) -> None: 

714 assert len(names) != 0 

715 self.names = names 

716 

717 def __eq__(self, other: object) -> bool: 

718 if not isinstance(other, ASTTrailingTypeSpecFundamental): 

719 return NotImplemented 

720 return self.names == other.names 

721 

722 def __hash__(self) -> int: 

723 return hash(self.names) 

724 

725 def _stringify(self, transform: StringifyTransform) -> str: 

726 return ' '.join(self.names) 

727 

728 def describe_signature(self, signode: TextElement, mode: str, 

729 env: BuildEnvironment, symbol: Symbol) -> None: 

730 first = True 

731 for n in self.names: 

732 if not first: 

733 signode += addnodes.desc_sig_space() 

734 else: 

735 first = False 

736 signode += addnodes.desc_sig_keyword_type(n, n) 

737 

738 

739class ASTTrailingTypeSpecName(ASTTrailingTypeSpec): 

740 def __init__(self, prefix: str, nestedName: ASTNestedName) -> None: 

741 self.prefix = prefix 

742 self.nestedName = nestedName 

743 

744 def __eq__(self, other: object) -> bool: 

745 if not isinstance(other, ASTTrailingTypeSpecName): 

746 return NotImplemented 

747 return ( 

748 self.prefix == other.prefix 

749 and self.nestedName == other.nestedName 

750 ) 

751 

752 def __hash__(self) -> int: 

753 return hash((self.prefix, self.nestedName)) 

754 

755 @property 

756 def name(self) -> ASTNestedName: 

757 return self.nestedName 

758 

759 def _stringify(self, transform: StringifyTransform) -> str: 

760 res = [] 

761 if self.prefix: 

762 res.append(self.prefix) 

763 res.append(' ') 

764 res.append(transform(self.nestedName)) 

765 return ''.join(res) 

766 

767 def describe_signature(self, signode: TextElement, mode: str, 

768 env: BuildEnvironment, symbol: Symbol) -> None: 

769 if self.prefix: 

770 signode += addnodes.desc_sig_keyword(self.prefix, self.prefix) 

771 signode += addnodes.desc_sig_space() 

772 self.nestedName.describe_signature(signode, mode, env, symbol=symbol) 

773 

774 

775class ASTFunctionParameter(ASTBase): 

776 def __init__(self, arg: ASTTypeWithInit | None, ellipsis: bool = False) -> None: 

777 self.arg = arg 

778 self.ellipsis = ellipsis 

779 

780 def __eq__(self, other: object) -> bool: 

781 if not isinstance(other, ASTFunctionParameter): 

782 return NotImplemented 

783 return self.arg == other.arg and self.ellipsis == other.ellipsis 

784 

785 def __hash__(self) -> int: 

786 return hash((self.arg, self.ellipsis)) 

787 

788 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

789 # the anchor will be our parent 

790 return symbol.parent.declaration.get_id(version, prefixed=False) 

791 

792 def _stringify(self, transform: StringifyTransform) -> str: 

793 if self.ellipsis: 

794 return '...' 

795 else: 

796 return transform(self.arg) 

797 

798 def describe_signature(self, signode: Any, mode: str, 

799 env: BuildEnvironment, symbol: Symbol) -> None: 

800 verify_description_mode(mode) 

801 if self.ellipsis: 

802 signode += addnodes.desc_sig_punctuation('...', '...') 

803 else: 

804 self.arg.describe_signature(signode, mode, env, symbol=symbol) 

805 

806 

807class ASTParameters(ASTBase): 

808 def __init__(self, args: list[ASTFunctionParameter], attrs: ASTAttributeList) -> None: 

809 self.args = args 

810 self.attrs = attrs 

811 

812 def __eq__(self, other: object) -> bool: 

813 if not isinstance(other, ASTParameters): 

814 return NotImplemented 

815 return self.args == other.args and self.attrs == other.attrs 

816 

817 def __hash__(self) -> int: 

818 return hash((self.args, self.attrs)) 

819 

820 @property 

821 def function_params(self) -> list[ASTFunctionParameter]: 

822 return self.args 

823 

824 def _stringify(self, transform: StringifyTransform) -> str: 

825 res = [] 

826 res.append('(') 

827 first = True 

828 for a in self.args: 

829 if not first: 

830 res.append(', ') 

831 first = False 

832 res.append(str(a)) 

833 res.append(')') 

834 if len(self.attrs) != 0: 

835 res.append(' ') 

836 res.append(transform(self.attrs)) 

837 return ''.join(res) 

838 

839 def describe_signature(self, signode: TextElement, mode: str, 

840 env: BuildEnvironment, symbol: Symbol) -> None: 

841 verify_description_mode(mode) 

842 multi_line_parameter_list = False 

843 test_node: Element = signode 

844 while test_node.parent: 

845 if not isinstance(test_node, addnodes.desc_signature): 

846 test_node = test_node.parent 

847 continue 

848 multi_line_parameter_list = test_node.get('multi_line_parameter_list', False) 

849 break 

850 

851 # only use the desc_parameterlist for the outer list, not for inner lists 

852 if mode == 'lastIsName': 

853 paramlist = addnodes.desc_parameterlist() 

854 paramlist['multi_line_parameter_list'] = multi_line_parameter_list 

855 for arg in self.args: 

856 param = addnodes.desc_parameter('', '', noemph=True) 

857 arg.describe_signature(param, 'param', env, symbol=symbol) 

858 paramlist += param 

859 signode += paramlist 

860 else: 

861 signode += addnodes.desc_sig_punctuation('(', '(') 

862 first = True 

863 for arg in self.args: 

864 if not first: 

865 signode += addnodes.desc_sig_punctuation(',', ',') 

866 signode += addnodes.desc_sig_space() 

867 first = False 

868 arg.describe_signature(signode, 'markType', env, symbol=symbol) 

869 signode += addnodes.desc_sig_punctuation(')', ')') 

870 

871 if len(self.attrs) != 0: 

872 signode += addnodes.desc_sig_space() 

873 self.attrs.describe_signature(signode) 

874 

875 

876class ASTDeclSpecsSimple(ASTBaseBase): 

877 def __init__(self, storage: str, threadLocal: str, inline: bool, 

878 restrict: bool, volatile: bool, const: bool, attrs: ASTAttributeList) -> None: 

879 self.storage = storage 

880 self.threadLocal = threadLocal 

881 self.inline = inline 

882 self.restrict = restrict 

883 self.volatile = volatile 

884 self.const = const 

885 self.attrs = attrs 

886 

887 def __eq__(self, other: object) -> bool: 

888 if not isinstance(other, ASTDeclSpecsSimple): 

889 return NotImplemented 

890 return ( 

891 self.storage == other.storage 

892 and self.threadLocal == other.threadLocal 

893 and self.inline == other.inline 

894 and self.restrict == other.restrict 

895 and self.volatile == other.volatile 

896 and self.const == other.const 

897 and self.attrs == other.attrs 

898 ) 

899 

900 def __hash__(self) -> int: 

901 return hash(( 

902 self.storage, 

903 self.threadLocal, 

904 self.inline, 

905 self.restrict, 

906 self.volatile, 

907 self.const, 

908 self.attrs, 

909 )) 

910 

911 def mergeWith(self, other: ASTDeclSpecsSimple) -> ASTDeclSpecsSimple: 

912 if not other: 

913 return self 

914 return ASTDeclSpecsSimple(self.storage or other.storage, 

915 self.threadLocal or other.threadLocal, 

916 self.inline or other.inline, 

917 self.volatile or other.volatile, 

918 self.const or other.const, 

919 self.restrict or other.restrict, 

920 self.attrs + other.attrs) 

921 

922 def _stringify(self, transform: StringifyTransform) -> str: 

923 res: list[str] = [] 

924 if len(self.attrs) != 0: 

925 res.append(transform(self.attrs)) 

926 if self.storage: 

927 res.append(self.storage) 

928 if self.threadLocal: 

929 res.append(self.threadLocal) 

930 if self.inline: 

931 res.append('inline') 

932 if self.restrict: 

933 res.append('restrict') 

934 if self.volatile: 

935 res.append('volatile') 

936 if self.const: 

937 res.append('const') 

938 return ' '.join(res) 

939 

940 def describe_signature(self, modifiers: list[Node]) -> None: 

941 def _add(modifiers: list[Node], text: str) -> None: 

942 if len(modifiers) != 0: 

943 modifiers.append(addnodes.desc_sig_space()) 

944 modifiers.append(addnodes.desc_sig_keyword(text, text)) 

945 

946 if len(modifiers) != 0 and len(self.attrs) != 0: 

947 modifiers.append(addnodes.desc_sig_space()) 

948 tempNode = nodes.TextElement() 

949 self.attrs.describe_signature(tempNode) 

950 modifiers.extend(tempNode.children) 

951 if self.storage: 

952 _add(modifiers, self.storage) 

953 if self.threadLocal: 

954 _add(modifiers, self.threadLocal) 

955 if self.inline: 

956 _add(modifiers, 'inline') 

957 if self.restrict: 

958 _add(modifiers, 'restrict') 

959 if self.volatile: 

960 _add(modifiers, 'volatile') 

961 if self.const: 

962 _add(modifiers, 'const') 

963 

964 

965class ASTDeclSpecs(ASTBase): 

966 def __init__(self, outer: str, 

967 leftSpecs: ASTDeclSpecsSimple, 

968 rightSpecs: ASTDeclSpecsSimple, 

969 trailing: ASTTrailingTypeSpec) -> None: 

970 # leftSpecs and rightSpecs are used for output 

971 # allSpecs are used for id generation TODO: remove? 

972 self.outer = outer 

973 self.leftSpecs = leftSpecs 

974 self.rightSpecs = rightSpecs 

975 self.allSpecs = self.leftSpecs.mergeWith(self.rightSpecs) 

976 self.trailingTypeSpec = trailing 

977 

978 def __eq__(self, other: object) -> bool: 

979 if not isinstance(other, ASTDeclSpecs): 

980 return NotImplemented 

981 return ( 

982 self.outer == other.outer 

983 and self.leftSpecs == other.leftSpecs 

984 and self.rightSpecs == other.rightSpecs 

985 and self.trailingTypeSpec == other.trailingTypeSpec 

986 ) 

987 

988 def __hash__(self) -> int: 

989 return hash(( 

990 self.outer, 

991 self.leftSpecs, 

992 self.rightSpecs, 

993 self.trailingTypeSpec, 

994 )) 

995 

996 def _stringify(self, transform: StringifyTransform) -> str: 

997 res: list[str] = [] 

998 l = transform(self.leftSpecs) 

999 if len(l) > 0: 

1000 res.append(l) 

1001 if self.trailingTypeSpec: 

1002 if len(res) > 0: 

1003 res.append(" ") 

1004 res.append(transform(self.trailingTypeSpec)) 

1005 r = str(self.rightSpecs) 

1006 if len(r) > 0: 

1007 if len(res) > 0: 

1008 res.append(" ") 

1009 res.append(r) 

1010 return "".join(res) 

1011 

1012 def describe_signature(self, signode: TextElement, mode: str, 

1013 env: BuildEnvironment, symbol: Symbol) -> None: 

1014 verify_description_mode(mode) 

1015 modifiers: list[Node] = [] 

1016 

1017 self.leftSpecs.describe_signature(modifiers) 

1018 

1019 for m in modifiers: 

1020 signode += m 

1021 if self.trailingTypeSpec: 

1022 if len(modifiers) > 0: 

1023 signode += addnodes.desc_sig_space() 

1024 self.trailingTypeSpec.describe_signature(signode, mode, env, 

1025 symbol=symbol) 

1026 modifiers = [] 

1027 self.rightSpecs.describe_signature(modifiers) 

1028 if len(modifiers) > 0: 

1029 signode += addnodes.desc_sig_space() 

1030 for m in modifiers: 

1031 signode += m 

1032 

1033 

1034# Declarator 

1035################################################################################ 

1036 

1037class ASTArray(ASTBase): 

1038 def __init__(self, static: bool, const: bool, volatile: bool, restrict: bool, 

1039 vla: bool, size: ASTExpression) -> None: 

1040 self.static = static 

1041 self.const = const 

1042 self.volatile = volatile 

1043 self.restrict = restrict 

1044 self.vla = vla 

1045 self.size = size 

1046 if vla: 

1047 assert size is None 

1048 if size is not None: 

1049 assert not vla 

1050 

1051 def __eq__(self, other: object) -> bool: 

1052 if not isinstance(other, ASTArray): 

1053 return NotImplemented 

1054 return ( 

1055 self.static == other.static 

1056 and self.const == other.const 

1057 and self.volatile == other.volatile 

1058 and self.restrict == other.restrict 

1059 and self.vla == other.vla 

1060 and self.size == other.size 

1061 ) 

1062 

1063 def __hash__(self) -> int: 

1064 return hash(( 

1065 self.static, 

1066 self.const, 

1067 self.volatile, 

1068 self.restrict, 

1069 self.vla, 

1070 self.size, 

1071 )) 

1072 

1073 def _stringify(self, transform: StringifyTransform) -> str: 

1074 el = [] 

1075 if self.static: 

1076 el.append('static') 

1077 if self.restrict: 

1078 el.append('restrict') 

1079 if self.volatile: 

1080 el.append('volatile') 

1081 if self.const: 

1082 el.append('const') 

1083 if self.vla: 

1084 return '[' + ' '.join(el) + '*]' 

1085 elif self.size: 

1086 el.append(transform(self.size)) 

1087 return '[' + ' '.join(el) + ']' 

1088 

1089 def describe_signature(self, signode: TextElement, mode: str, 

1090 env: BuildEnvironment, symbol: Symbol) -> None: 

1091 verify_description_mode(mode) 

1092 signode += addnodes.desc_sig_punctuation('[', '[') 

1093 addSpace = False 

1094 

1095 def _add(signode: TextElement, text: str) -> bool: 

1096 if addSpace: 

1097 signode += addnodes.desc_sig_space() 

1098 signode += addnodes.desc_sig_keyword(text, text) 

1099 return True 

1100 

1101 if self.static: 

1102 addSpace = _add(signode, 'static') 

1103 if self.restrict: 

1104 addSpace = _add(signode, 'restrict') 

1105 if self.volatile: 

1106 addSpace = _add(signode, 'volatile') 

1107 if self.const: 

1108 addSpace = _add(signode, 'const') 

1109 if self.vla: 

1110 signode += addnodes.desc_sig_punctuation('*', '*') 

1111 elif self.size: 

1112 if addSpace: 

1113 signode += addnodes.desc_sig_space() 

1114 self.size.describe_signature(signode, 'markType', env, symbol) 

1115 signode += addnodes.desc_sig_punctuation(']', ']') 

1116 

1117 

1118class ASTDeclarator(ASTBase): 

1119 @property 

1120 def name(self) -> ASTNestedName: 

1121 raise NotImplementedError(repr(self)) 

1122 

1123 @property 

1124 def function_params(self) -> list[ASTFunctionParameter]: 

1125 raise NotImplementedError(repr(self)) 

1126 

1127 def require_space_after_declSpecs(self) -> bool: 

1128 raise NotImplementedError(repr(self)) 

1129 

1130 

1131class ASTDeclaratorNameParam(ASTDeclarator): 

1132 def __init__(self, declId: ASTNestedName, 

1133 arrayOps: list[ASTArray], param: ASTParameters) -> None: 

1134 self.declId = declId 

1135 self.arrayOps = arrayOps 

1136 self.param = param 

1137 

1138 def __eq__(self, other: object) -> bool: 

1139 if not isinstance(other, ASTDeclaratorNameParam): 

1140 return NotImplemented 

1141 return ( 

1142 self.declId == other.declId 

1143 and self.arrayOps == other.arrayOps 

1144 and self.param == other.param 

1145 ) 

1146 

1147 def __hash__(self) -> int: 

1148 return hash((self.declId, self.arrayOps, self.param)) 

1149 

1150 @property 

1151 def name(self) -> ASTNestedName: 

1152 return self.declId 

1153 

1154 @property 

1155 def function_params(self) -> list[ASTFunctionParameter]: 

1156 return self.param.function_params 

1157 

1158 # ------------------------------------------------------------------------ 

1159 

1160 def require_space_after_declSpecs(self) -> bool: 

1161 return self.declId is not None 

1162 

1163 def _stringify(self, transform: StringifyTransform) -> str: 

1164 res = [] 

1165 if self.declId: 

1166 res.append(transform(self.declId)) 

1167 res.extend(transform(op) for op in self.arrayOps) 

1168 if self.param: 

1169 res.append(transform(self.param)) 

1170 return ''.join(res) 

1171 

1172 def describe_signature(self, signode: TextElement, mode: str, 

1173 env: BuildEnvironment, symbol: Symbol) -> None: 

1174 verify_description_mode(mode) 

1175 if self.declId: 

1176 self.declId.describe_signature(signode, mode, env, symbol) 

1177 for op in self.arrayOps: 

1178 op.describe_signature(signode, mode, env, symbol) 

1179 if self.param: 

1180 self.param.describe_signature(signode, mode, env, symbol) 

1181 

1182 

1183class ASTDeclaratorNameBitField(ASTDeclarator): 

1184 def __init__(self, declId: ASTNestedName, size: ASTExpression) -> None: 

1185 self.declId = declId 

1186 self.size = size 

1187 

1188 def __eq__(self, other: object) -> bool: 

1189 if not isinstance(other, ASTDeclaratorNameBitField): 

1190 return NotImplemented 

1191 return self.declId == other.declId and self.size == other.size 

1192 

1193 def __hash__(self) -> int: 

1194 return hash((self.declId, self.size)) 

1195 

1196 @property 

1197 def name(self) -> ASTNestedName: 

1198 return self.declId 

1199 

1200 # ------------------------------------------------------------------------ 

1201 

1202 def require_space_after_declSpecs(self) -> bool: 

1203 return self.declId is not None 

1204 

1205 def _stringify(self, transform: StringifyTransform) -> str: 

1206 res = [] 

1207 if self.declId: 

1208 res.append(transform(self.declId)) 

1209 res.append(" : ") 

1210 res.append(transform(self.size)) 

1211 return ''.join(res) 

1212 

1213 def describe_signature(self, signode: TextElement, mode: str, 

1214 env: BuildEnvironment, symbol: Symbol) -> None: 

1215 verify_description_mode(mode) 

1216 if self.declId: 

1217 self.declId.describe_signature(signode, mode, env, symbol) 

1218 signode += addnodes.desc_sig_space() 

1219 signode += addnodes.desc_sig_punctuation(':', ':') 

1220 signode += addnodes.desc_sig_space() 

1221 self.size.describe_signature(signode, mode, env, symbol) 

1222 

1223 

1224class ASTDeclaratorPtr(ASTDeclarator): 

1225 def __init__(self, next: ASTDeclarator, restrict: bool, volatile: bool, const: bool, 

1226 attrs: ASTAttributeList) -> None: 

1227 assert next 

1228 self.next = next 

1229 self.restrict = restrict 

1230 self.volatile = volatile 

1231 self.const = const 

1232 self.attrs = attrs 

1233 

1234 def __eq__(self, other: object) -> bool: 

1235 if not isinstance(other, ASTDeclaratorPtr): 

1236 return NotImplemented 

1237 return ( 

1238 self.next == other.next 

1239 and self.restrict == other.restrict 

1240 and self.volatile == other.volatile 

1241 and self.const == other.const 

1242 and self.attrs == other.attrs 

1243 ) 

1244 

1245 def __hash__(self) -> int: 

1246 return hash((self.next, self.restrict, self.volatile, self.const, self.attrs)) 

1247 

1248 @property 

1249 def name(self) -> ASTNestedName: 

1250 return self.next.name 

1251 

1252 @property 

1253 def function_params(self) -> list[ASTFunctionParameter]: 

1254 return self.next.function_params 

1255 

1256 def require_space_after_declSpecs(self) -> bool: 

1257 return self.const or self.volatile or self.restrict or \ 

1258 len(self.attrs) > 0 or \ 

1259 self.next.require_space_after_declSpecs() 

1260 

1261 def _stringify(self, transform: StringifyTransform) -> str: 

1262 res = ['*'] 

1263 res.append(transform(self.attrs)) 

1264 if len(self.attrs) != 0 and (self.restrict or self.volatile or self.const): 

1265 res.append(' ') 

1266 if self.restrict: 

1267 res.append('restrict') 

1268 if self.volatile: 

1269 if self.restrict: 

1270 res.append(' ') 

1271 res.append('volatile') 

1272 if self.const: 

1273 if self.restrict or self.volatile: 

1274 res.append(' ') 

1275 res.append('const') 

1276 if self.const or self.volatile or self.restrict or len(self.attrs) > 0: 

1277 if self.next.require_space_after_declSpecs(): 

1278 res.append(' ') 

1279 res.append(transform(self.next)) 

1280 return ''.join(res) 

1281 

1282 def describe_signature(self, signode: TextElement, mode: str, 

1283 env: BuildEnvironment, symbol: Symbol) -> None: 

1284 verify_description_mode(mode) 

1285 signode += addnodes.desc_sig_punctuation('*', '*') 

1286 self.attrs.describe_signature(signode) 

1287 if len(self.attrs) != 0 and (self.restrict or self.volatile or self.const): 

1288 signode += addnodes.desc_sig_space() 

1289 

1290 def _add_anno(signode: TextElement, text: str) -> None: 

1291 signode += addnodes.desc_sig_keyword(text, text) 

1292 

1293 if self.restrict: 

1294 _add_anno(signode, 'restrict') 

1295 if self.volatile: 

1296 if self.restrict: 

1297 signode += addnodes.desc_sig_space() 

1298 _add_anno(signode, 'volatile') 

1299 if self.const: 

1300 if self.restrict or self.volatile: 

1301 signode += addnodes.desc_sig_space() 

1302 _add_anno(signode, 'const') 

1303 if self.const or self.volatile or self.restrict or len(self.attrs) > 0: 

1304 if self.next.require_space_after_declSpecs(): 

1305 signode += addnodes.desc_sig_space() 

1306 self.next.describe_signature(signode, mode, env, symbol) 

1307 

1308 

1309class ASTDeclaratorParen(ASTDeclarator): 

1310 def __init__(self, inner: ASTDeclarator, next: ASTDeclarator) -> None: 

1311 assert inner 

1312 assert next 

1313 self.inner = inner 

1314 self.next = next 

1315 # TODO: we assume the name and params are in inner 

1316 

1317 def __eq__(self, other: object) -> bool: 

1318 if not isinstance(other, ASTDeclaratorParen): 

1319 return NotImplemented 

1320 return self.inner == other.inner and self.next == other.next 

1321 

1322 def __hash__(self) -> int: 

1323 return hash((self.inner, self.next)) 

1324 

1325 @property 

1326 def name(self) -> ASTNestedName: 

1327 return self.inner.name 

1328 

1329 @property 

1330 def function_params(self) -> list[ASTFunctionParameter]: 

1331 return self.inner.function_params 

1332 

1333 def require_space_after_declSpecs(self) -> bool: 

1334 return True 

1335 

1336 def _stringify(self, transform: StringifyTransform) -> str: 

1337 res = ['('] 

1338 res.append(transform(self.inner)) 

1339 res.append(')') 

1340 res.append(transform(self.next)) 

1341 return ''.join(res) 

1342 

1343 def describe_signature(self, signode: TextElement, mode: str, 

1344 env: BuildEnvironment, symbol: Symbol) -> None: 

1345 verify_description_mode(mode) 

1346 signode += addnodes.desc_sig_punctuation('(', '(') 

1347 self.inner.describe_signature(signode, mode, env, symbol) 

1348 signode += addnodes.desc_sig_punctuation(')', ')') 

1349 self.next.describe_signature(signode, "noneIsName", env, symbol) 

1350 

1351 

1352# Initializer 

1353################################################################################ 

1354 

1355class ASTParenExprList(ASTBaseParenExprList): 

1356 def __init__(self, exprs: list[ASTExpression]) -> None: 

1357 self.exprs = exprs 

1358 

1359 def __eq__(self, other: object) -> bool: 

1360 if not isinstance(other, ASTParenExprList): 

1361 return NotImplemented 

1362 return self.exprs == other.exprs 

1363 

1364 def __hash__(self) -> int: 

1365 return hash(self.exprs) 

1366 

1367 def _stringify(self, transform: StringifyTransform) -> str: 

1368 exprs = [transform(e) for e in self.exprs] 

1369 return '(%s)' % ', '.join(exprs) 

1370 

1371 def describe_signature(self, signode: TextElement, mode: str, 

1372 env: BuildEnvironment, symbol: Symbol) -> None: 

1373 verify_description_mode(mode) 

1374 signode += addnodes.desc_sig_punctuation('(', '(') 

1375 first = True 

1376 for e in self.exprs: 

1377 if not first: 

1378 signode += addnodes.desc_sig_punctuation(',', ',') 

1379 signode += addnodes.desc_sig_space() 

1380 else: 

1381 first = False 

1382 e.describe_signature(signode, mode, env, symbol) 

1383 signode += addnodes.desc_sig_punctuation(')', ')') 

1384 

1385 

1386class ASTBracedInitList(ASTBase): 

1387 def __init__(self, exprs: list[ASTExpression], trailingComma: bool) -> None: 

1388 self.exprs = exprs 

1389 self.trailingComma = trailingComma 

1390 

1391 def __eq__(self, other: object) -> bool: 

1392 if not isinstance(other, ASTBracedInitList): 

1393 return NotImplemented 

1394 return self.exprs == other.exprs and self.trailingComma == other.trailingComma 

1395 

1396 def __hash__(self) -> int: 

1397 return hash((self.exprs, self.trailingComma)) 

1398 

1399 def _stringify(self, transform: StringifyTransform) -> str: 

1400 exprs = ', '.join(transform(e) for e in self.exprs) 

1401 trailingComma = ',' if self.trailingComma else '' 

1402 return f'{{{exprs}{trailingComma}}}' 

1403 

1404 def describe_signature(self, signode: TextElement, mode: str, 

1405 env: BuildEnvironment, symbol: Symbol) -> None: 

1406 verify_description_mode(mode) 

1407 signode += addnodes.desc_sig_punctuation('{', '{') 

1408 first = True 

1409 for e in self.exprs: 

1410 if not first: 

1411 signode += addnodes.desc_sig_punctuation(',', ',') 

1412 signode += addnodes.desc_sig_space() 

1413 else: 

1414 first = False 

1415 e.describe_signature(signode, mode, env, symbol) 

1416 if self.trailingComma: 

1417 signode += addnodes.desc_sig_punctuation(',', ',') 

1418 signode += addnodes.desc_sig_punctuation('}', '}') 

1419 

1420 

1421class ASTInitializer(ASTBase): 

1422 def __init__(self, value: ASTBracedInitList | ASTExpression, 

1423 hasAssign: bool = True) -> None: 

1424 self.value = value 

1425 self.hasAssign = hasAssign 

1426 

1427 def __eq__(self, other: object) -> bool: 

1428 if not isinstance(other, ASTInitializer): 

1429 return NotImplemented 

1430 return self.value == other.value and self.hasAssign == other.hasAssign 

1431 

1432 def __hash__(self) -> int: 

1433 return hash((self.value, self.hasAssign)) 

1434 

1435 def _stringify(self, transform: StringifyTransform) -> str: 

1436 val = transform(self.value) 

1437 if self.hasAssign: 

1438 return ' = ' + val 

1439 else: 

1440 return val 

1441 

1442 def describe_signature(self, signode: TextElement, mode: str, 

1443 env: BuildEnvironment, symbol: Symbol) -> None: 

1444 verify_description_mode(mode) 

1445 if self.hasAssign: 

1446 signode += addnodes.desc_sig_space() 

1447 signode += addnodes.desc_sig_punctuation('=', '=') 

1448 signode += addnodes.desc_sig_space() 

1449 self.value.describe_signature(signode, 'markType', env, symbol) 

1450 

1451 

1452class ASTType(ASTBase): 

1453 def __init__(self, declSpecs: ASTDeclSpecs, decl: ASTDeclarator) -> None: 

1454 assert declSpecs 

1455 assert decl 

1456 self.declSpecs = declSpecs 

1457 self.decl = decl 

1458 

1459 def __eq__(self, other: object) -> bool: 

1460 if not isinstance(other, ASTType): 

1461 return NotImplemented 

1462 return self.declSpecs == other.declSpecs and self.decl == other.decl 

1463 

1464 def __hash__(self) -> int: 

1465 return hash((self.declSpecs, self.decl)) 

1466 

1467 @property 

1468 def name(self) -> ASTNestedName: 

1469 return self.decl.name 

1470 

1471 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

1472 return symbol.get_full_nested_name().get_id(version) 

1473 

1474 @property 

1475 def function_params(self) -> list[ASTFunctionParameter]: 

1476 return self.decl.function_params 

1477 

1478 def _stringify(self, transform: StringifyTransform) -> str: 

1479 res = [] 

1480 declSpecs = transform(self.declSpecs) 

1481 res.append(declSpecs) 

1482 if self.decl.require_space_after_declSpecs() and len(declSpecs) > 0: 

1483 res.append(' ') 

1484 res.append(transform(self.decl)) 

1485 return ''.join(res) 

1486 

1487 def get_type_declaration_prefix(self) -> str: 

1488 if self.declSpecs.trailingTypeSpec: 

1489 return 'typedef' 

1490 else: 

1491 return 'type' 

1492 

1493 def describe_signature(self, signode: TextElement, mode: str, 

1494 env: BuildEnvironment, symbol: Symbol) -> None: 

1495 verify_description_mode(mode) 

1496 self.declSpecs.describe_signature(signode, 'markType', env, symbol) 

1497 if (self.decl.require_space_after_declSpecs() and 

1498 len(str(self.declSpecs)) > 0): 

1499 signode += addnodes.desc_sig_space() 

1500 # for parameters that don't really declare new names we get 'markType', 

1501 # this should not be propagated, but be 'noneIsName'. 

1502 if mode == 'markType': 

1503 mode = 'noneIsName' 

1504 self.decl.describe_signature(signode, mode, env, symbol) 

1505 

1506 

1507class ASTTypeWithInit(ASTBase): 

1508 def __init__(self, type: ASTType, init: ASTInitializer) -> None: 

1509 self.type = type 

1510 self.init = init 

1511 

1512 def __eq__(self, other: object) -> bool: 

1513 if not isinstance(other, ASTTypeWithInit): 

1514 return NotImplemented 

1515 return self.type == other.type and self.init == other.init 

1516 

1517 def __hash__(self) -> int: 

1518 return hash((self.type, self.init)) 

1519 

1520 @property 

1521 def name(self) -> ASTNestedName: 

1522 return self.type.name 

1523 

1524 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

1525 return self.type.get_id(version, objectType, symbol) 

1526 

1527 def _stringify(self, transform: StringifyTransform) -> str: 

1528 res = [] 

1529 res.append(transform(self.type)) 

1530 if self.init: 

1531 res.append(transform(self.init)) 

1532 return ''.join(res) 

1533 

1534 def describe_signature(self, signode: TextElement, mode: str, 

1535 env: BuildEnvironment, symbol: Symbol) -> None: 

1536 verify_description_mode(mode) 

1537 self.type.describe_signature(signode, mode, env, symbol) 

1538 if self.init: 

1539 self.init.describe_signature(signode, mode, env, symbol) 

1540 

1541 

1542class ASTMacroParameter(ASTBase): 

1543 def __init__(self, arg: ASTNestedName | None, ellipsis: bool = False, 

1544 variadic: bool = False) -> None: 

1545 self.arg = arg 

1546 self.ellipsis = ellipsis 

1547 self.variadic = variadic 

1548 

1549 def __eq__(self, other: object) -> bool: 

1550 if not isinstance(other, ASTMacroParameter): 

1551 return NotImplemented 

1552 return ( 

1553 self.arg == other.arg 

1554 and self.ellipsis == other.ellipsis 

1555 and self.variadic == other.variadic 

1556 ) 

1557 

1558 def __hash__(self) -> int: 

1559 return hash((self.arg, self.ellipsis, self.variadic)) 

1560 

1561 def _stringify(self, transform: StringifyTransform) -> str: 

1562 if self.ellipsis: 

1563 return '...' 

1564 elif self.variadic: 

1565 return transform(self.arg) + '...' 

1566 else: 

1567 return transform(self.arg) 

1568 

1569 def describe_signature(self, signode: Any, mode: str, 

1570 env: BuildEnvironment, symbol: Symbol) -> None: 

1571 verify_description_mode(mode) 

1572 if self.ellipsis: 

1573 signode += addnodes.desc_sig_punctuation('...', '...') 

1574 elif self.variadic: 

1575 name = str(self) 

1576 signode += addnodes.desc_sig_name(name, name) 

1577 else: 

1578 self.arg.describe_signature(signode, mode, env, symbol=symbol) 

1579 

1580 

1581class ASTMacro(ASTBase): 

1582 def __init__(self, ident: ASTNestedName, args: list[ASTMacroParameter] | None) -> None: 

1583 self.ident = ident 

1584 self.args = args 

1585 

1586 def __eq__(self, other: object) -> bool: 

1587 if not isinstance(other, ASTMacro): 

1588 return NotImplemented 

1589 return self.ident == other.ident and self.args == other.args 

1590 

1591 def __hash__(self) -> int: 

1592 return hash((self.ident, self.args)) 

1593 

1594 @property 

1595 def name(self) -> ASTNestedName: 

1596 return self.ident 

1597 

1598 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

1599 return symbol.get_full_nested_name().get_id(version) 

1600 

1601 def _stringify(self, transform: StringifyTransform) -> str: 

1602 res = [] 

1603 res.append(transform(self.ident)) 

1604 if self.args is not None: 

1605 res.append('(') 

1606 first = True 

1607 for arg in self.args: 

1608 if not first: 

1609 res.append(', ') 

1610 first = False 

1611 res.append(transform(arg)) 

1612 res.append(')') 

1613 return ''.join(res) 

1614 

1615 def describe_signature(self, signode: TextElement, mode: str, 

1616 env: BuildEnvironment, symbol: Symbol) -> None: 

1617 verify_description_mode(mode) 

1618 self.ident.describe_signature(signode, mode, env, symbol) 

1619 if self.args is None: 

1620 return 

1621 paramlist = addnodes.desc_parameterlist() 

1622 for arg in self.args: 

1623 param = addnodes.desc_parameter('', '', noemph=True) 

1624 arg.describe_signature(param, 'param', env, symbol=symbol) 

1625 paramlist += param 

1626 signode += paramlist 

1627 

1628 

1629class ASTStruct(ASTBase): 

1630 def __init__(self, name: ASTNestedName) -> None: 

1631 self.name = name 

1632 

1633 def __eq__(self, other: object) -> bool: 

1634 if not isinstance(other, ASTStruct): 

1635 return NotImplemented 

1636 return self.name == other.name 

1637 

1638 def __hash__(self) -> int: 

1639 return hash(self.name) 

1640 

1641 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

1642 return symbol.get_full_nested_name().get_id(version) 

1643 

1644 def _stringify(self, transform: StringifyTransform) -> str: 

1645 return transform(self.name) 

1646 

1647 def describe_signature(self, signode: TextElement, mode: str, 

1648 env: BuildEnvironment, symbol: Symbol) -> None: 

1649 verify_description_mode(mode) 

1650 self.name.describe_signature(signode, mode, env, symbol=symbol) 

1651 

1652 

1653class ASTUnion(ASTBase): 

1654 def __init__(self, name: ASTNestedName) -> None: 

1655 self.name = name 

1656 

1657 def __eq__(self, other: object) -> bool: 

1658 if not isinstance(other, ASTUnion): 

1659 return NotImplemented 

1660 return self.name == other.name 

1661 

1662 def __hash__(self) -> int: 

1663 return hash(self.name) 

1664 

1665 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

1666 return symbol.get_full_nested_name().get_id(version) 

1667 

1668 def _stringify(self, transform: StringifyTransform) -> str: 

1669 return transform(self.name) 

1670 

1671 def describe_signature(self, signode: TextElement, mode: str, 

1672 env: BuildEnvironment, symbol: Symbol) -> None: 

1673 verify_description_mode(mode) 

1674 self.name.describe_signature(signode, mode, env, symbol=symbol) 

1675 

1676 

1677class ASTEnum(ASTBase): 

1678 def __init__(self, name: ASTNestedName) -> None: 

1679 self.name = name 

1680 

1681 def __eq__(self, other: object) -> bool: 

1682 if not isinstance(other, ASTEnum): 

1683 return NotImplemented 

1684 return self.name == other.name 

1685 

1686 def __hash__(self) -> int: 

1687 return hash(self.name) 

1688 

1689 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

1690 return symbol.get_full_nested_name().get_id(version) 

1691 

1692 def _stringify(self, transform: StringifyTransform) -> str: 

1693 return transform(self.name) 

1694 

1695 def describe_signature(self, signode: TextElement, mode: str, 

1696 env: BuildEnvironment, symbol: Symbol) -> None: 

1697 verify_description_mode(mode) 

1698 self.name.describe_signature(signode, mode, env, symbol=symbol) 

1699 

1700 

1701class ASTEnumerator(ASTBase): 

1702 def __init__(self, name: ASTNestedName, init: ASTInitializer | None, 

1703 attrs: ASTAttributeList) -> None: 

1704 self.name = name 

1705 self.init = init 

1706 self.attrs = attrs 

1707 

1708 def __eq__(self, other: object) -> bool: 

1709 if not isinstance(other, ASTEnumerator): 

1710 return NotImplemented 

1711 return ( 

1712 self.name == other.name 

1713 and self.init == other.init 

1714 and self.attrs == other.attrs 

1715 ) 

1716 

1717 def __hash__(self) -> int: 

1718 return hash((self.name, self.init, self.attrs)) 

1719 

1720 def get_id(self, version: int, objectType: str, symbol: Symbol) -> str: 

1721 return symbol.get_full_nested_name().get_id(version) 

1722 

1723 def _stringify(self, transform: StringifyTransform) -> str: 

1724 res = [] 

1725 res.append(transform(self.name)) 

1726 if len(self.attrs) != 0: 

1727 res.append(' ') 

1728 res.append(transform(self.attrs)) 

1729 if self.init: 

1730 res.append(transform(self.init)) 

1731 return ''.join(res) 

1732 

1733 def describe_signature(self, signode: TextElement, mode: str, 

1734 env: BuildEnvironment, symbol: Symbol) -> None: 

1735 verify_description_mode(mode) 

1736 self.name.describe_signature(signode, mode, env, symbol) 

1737 if len(self.attrs) != 0: 

1738 signode += addnodes.desc_sig_space() 

1739 self.attrs.describe_signature(signode) 

1740 if self.init: 

1741 self.init.describe_signature(signode, 'markType', env, symbol) 

1742 

1743 

1744class ASTDeclaration(ASTBaseBase): 

1745 def __init__(self, objectType: str, directiveType: str | None, 

1746 declaration: DeclarationType | ASTFunctionParameter, 

1747 semicolon: bool = False) -> None: 

1748 self.objectType = objectType 

1749 self.directiveType = directiveType 

1750 self.declaration = declaration 

1751 self.semicolon = semicolon 

1752 

1753 self.symbol: Symbol | None = None 

1754 # set by CObject._add_enumerator_to_parent 

1755 self.enumeratorScopedSymbol: Symbol | None = None 

1756 

1757 # the cache assumes that by the time get_newest_id is called, no 

1758 # further changes will be made to this object 

1759 self._newest_id_cache: str | None = None 

1760 

1761 def __eq__(self, other: object) -> bool: 

1762 if not isinstance(other, ASTDeclaration): 

1763 return NotImplemented 

1764 return ( 

1765 self.objectType == other.objectType 

1766 and self.directiveType == other.directiveType 

1767 and self.declaration == other.declaration 

1768 and self.semicolon == other.semicolon 

1769 and self.symbol == other.symbol 

1770 and self.enumeratorScopedSymbol == other.enumeratorScopedSymbol 

1771 ) 

1772 

1773 def clone(self) -> ASTDeclaration: 

1774 return ASTDeclaration(self.objectType, self.directiveType, 

1775 self.declaration.clone(), self.semicolon) 

1776 

1777 @property 

1778 def name(self) -> ASTNestedName: 

1779 decl = cast(DeclarationType, self.declaration) 

1780 return decl.name 

1781 

1782 @property 

1783 def function_params(self) -> list[ASTFunctionParameter] | None: 

1784 if self.objectType != 'function': 

1785 return None 

1786 decl = cast(ASTType, self.declaration) 

1787 return decl.function_params 

1788 

1789 def get_id(self, version: int, prefixed: bool = True) -> str: 

1790 if self.objectType == 'enumerator' and self.enumeratorScopedSymbol: 

1791 return self.enumeratorScopedSymbol.declaration.get_id(version, prefixed) 

1792 id_ = self.declaration.get_id(version, self.objectType, self.symbol) 

1793 if prefixed: 

1794 return _id_prefix[version] + id_ 

1795 else: 

1796 return id_ 

1797 

1798 def get_newest_id(self) -> str: 

1799 if self._newest_id_cache is None: 

1800 self._newest_id_cache = self.get_id(_max_id, True) 

1801 return self._newest_id_cache 

1802 

1803 def _stringify(self, transform: StringifyTransform) -> str: 

1804 res = transform(self.declaration) 

1805 if self.semicolon: 

1806 res += ';' 

1807 return res 

1808 

1809 def describe_signature(self, signode: TextElement, mode: str, 

1810 env: BuildEnvironment, options: dict[str, bool]) -> None: 

1811 verify_description_mode(mode) 

1812 assert self.symbol 

1813 # The caller of the domain added a desc_signature node. 

1814 # Always enable multiline: 

1815 signode['is_multiline'] = True 

1816 # Put each line in a desc_signature_line node. 

1817 mainDeclNode = addnodes.desc_signature_line() 

1818 mainDeclNode.sphinx_line_type = 'declarator' 

1819 mainDeclNode['add_permalink'] = not self.symbol.isRedeclaration 

1820 signode += mainDeclNode 

1821 

1822 if self.objectType in {'member', 'function', 'macro'}: 

1823 pass 

1824 elif self.objectType == 'struct': 

1825 mainDeclNode += addnodes.desc_sig_keyword('struct', 'struct') 

1826 mainDeclNode += addnodes.desc_sig_space() 

1827 elif self.objectType == 'union': 

1828 mainDeclNode += addnodes.desc_sig_keyword('union', 'union') 

1829 mainDeclNode += addnodes.desc_sig_space() 

1830 elif self.objectType == 'enum': 

1831 mainDeclNode += addnodes.desc_sig_keyword('enum', 'enum') 

1832 mainDeclNode += addnodes.desc_sig_space() 

1833 elif self.objectType == 'enumerator': 

1834 mainDeclNode += addnodes.desc_sig_keyword('enumerator', 'enumerator') 

1835 mainDeclNode += addnodes.desc_sig_space() 

1836 elif self.objectType == 'type': 

1837 decl = cast(ASTType, self.declaration) 

1838 prefix = decl.get_type_declaration_prefix() 

1839 mainDeclNode += addnodes.desc_sig_keyword(prefix, prefix) 

1840 mainDeclNode += addnodes.desc_sig_space() 

1841 else: 

1842 raise AssertionError 

1843 self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol) 

1844 if self.semicolon: 

1845 mainDeclNode += addnodes.desc_sig_punctuation(';', ';')