diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/src/ast_src.rs | 379 | ||||
-rw-r--r-- | xtask/src/codegen.rs | 5 | ||||
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 257 | ||||
-rw-r--r-- | xtask/src/lib.rs | 1 |
4 files changed, 518 insertions, 124 deletions
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index d9f51ec39..74a87e900 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -70,7 +70,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
70 | "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super", | 70 | "match", "mod", "move", "mut", "pub", "ref", "return", "self", "static", "struct", "super", |
71 | "trait", "true", "try", "type", "unsafe", "use", "where", "while", | 71 | "trait", "true", "try", "type", "unsafe", "use", "where", "while", |
72 | ], | 72 | ], |
73 | contextual_keywords: &["auto", "default", "existential", "union"], | 73 | contextual_keywords: &["auto", "default", "existential", "union", "raw"], |
74 | literals: &[ | 74 | literals: &[ |
75 | "INT_NUMBER", | 75 | "INT_NUMBER", |
76 | "FLOAT_NUMBER", | 76 | "FLOAT_NUMBER", |
@@ -227,6 +227,7 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { | |||
227 | pub(crate) struct AstSrc<'a> { | 227 | pub(crate) struct AstSrc<'a> { |
228 | pub(crate) nodes: &'a [AstNodeSrc<'a>], | 228 | pub(crate) nodes: &'a [AstNodeSrc<'a>], |
229 | pub(crate) enums: &'a [AstEnumSrc<'a>], | 229 | pub(crate) enums: &'a [AstEnumSrc<'a>], |
230 | pub(crate) token_enums: &'a [AstEnumSrc<'a>], | ||
230 | } | 231 | } |
231 | 232 | ||
232 | pub(crate) struct AstNodeSrc<'a> { | 233 | pub(crate) struct AstNodeSrc<'a> { |
@@ -297,235 +298,311 @@ macro_rules! ast_enums { | |||
297 | 298 | ||
298 | pub(crate) const AST_SRC: AstSrc = AstSrc { | 299 | pub(crate) const AST_SRC: AstSrc = AstSrc { |
299 | nodes: &ast_nodes! { | 300 | nodes: &ast_nodes! { |
300 | struct SourceFile: ModuleItemOwner, FnDefOwner { | 301 | struct SourceFile: ModuleItemOwner, FnDefOwner, AttrsOwner { |
301 | modules: [Module], | 302 | modules: [Module], |
302 | } | 303 | } |
303 | 304 | ||
304 | struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { | 305 | struct FnDef: VisibilityOwner, NameOwner, TypeParamsOwner, DocCommentsOwner, AttrsOwner { |
306 | Abi, | ||
307 | ConstKw, | ||
308 | DefaultKw, | ||
309 | AsyncKw, | ||
310 | UnsafeKw, | ||
311 | FnKw, | ||
305 | ParamList, | 312 | ParamList, |
306 | RetType, | 313 | RetType, |
307 | body: BlockExpr, | 314 | body: BlockExpr, |
315 | Semi | ||
308 | } | 316 | } |
309 | 317 | ||
310 | struct RetType { TypeRef } | 318 | struct RetType { ThinArrow, TypeRef } |
311 | 319 | ||
312 | struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | 320 | struct StructDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { |
321 | StructKw, | ||
322 | FieldDefList, | ||
323 | Semi | ||
313 | } | 324 | } |
314 | 325 | ||
315 | struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | 326 | struct UnionDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { |
327 | UnionKw, | ||
316 | RecordFieldDefList, | 328 | RecordFieldDefList, |
317 | } | 329 | } |
318 | 330 | ||
319 | struct RecordFieldDefList { fields: [RecordFieldDef] } | 331 | struct RecordFieldDefList { LCurly, fields: [RecordFieldDef], RCurly } |
320 | struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } | 332 | struct RecordFieldDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { } |
321 | 333 | ||
322 | struct TupleFieldDefList { fields: [TupleFieldDef] } | 334 | struct TupleFieldDefList { LParen, fields: [TupleFieldDef], RParen } |
323 | struct TupleFieldDef: VisibilityOwner, AttrsOwner { | 335 | struct TupleFieldDef: VisibilityOwner, AttrsOwner { |
324 | TypeRef, | 336 | TypeRef, |
325 | } | 337 | } |
326 | 338 | ||
327 | struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { | 339 | struct EnumDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner { |
340 | EnumKw, | ||
328 | variant_list: EnumVariantList, | 341 | variant_list: EnumVariantList, |
329 | } | 342 | } |
330 | struct EnumVariantList { | 343 | struct EnumVariantList { |
344 | LCurly, | ||
331 | variants: [EnumVariant], | 345 | variants: [EnumVariant], |
346 | RCurly | ||
332 | } | 347 | } |
333 | struct EnumVariant: NameOwner, DocCommentsOwner, AttrsOwner { | 348 | struct EnumVariant: VisibilityOwner, NameOwner, DocCommentsOwner, AttrsOwner { |
349 | FieldDefList, | ||
350 | Eq, | ||
334 | Expr | 351 | Expr |
335 | } | 352 | } |
336 | 353 | ||
337 | struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { | 354 | struct TraitDef: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner, TypeParamsOwner, TypeBoundsOwner { |
355 | UnsafeKw, | ||
356 | AutoKw, | ||
357 | TraitKw, | ||
338 | ItemList, | 358 | ItemList, |
339 | } | 359 | } |
340 | 360 | ||
341 | struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { | 361 | struct Module: VisibilityOwner, NameOwner, AttrsOwner, DocCommentsOwner { |
362 | ModKw, | ||
342 | ItemList, | 363 | ItemList, |
364 | Semi | ||
343 | } | 365 | } |
344 | 366 | ||
345 | struct ItemList: FnDefOwner, ModuleItemOwner { | 367 | struct ItemList: FnDefOwner, ModuleItemOwner { |
368 | LCurly, | ||
346 | impl_items: [ImplItem], | 369 | impl_items: [ImplItem], |
370 | RCurly | ||
347 | } | 371 | } |
348 | 372 | ||
349 | struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { | 373 | struct ConstDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { |
374 | DefaultKw, | ||
375 | ConstKw, | ||
376 | Eq, | ||
350 | body: Expr, | 377 | body: Expr, |
378 | Semi | ||
351 | } | 379 | } |
352 | 380 | ||
353 | struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { | 381 | struct StaticDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeAscriptionOwner { |
382 | StaticKw, | ||
383 | MutKw, | ||
384 | Eq, | ||
354 | body: Expr, | 385 | body: Expr, |
386 | Semi | ||
355 | } | 387 | } |
356 | 388 | ||
357 | struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { | 389 | struct TypeAliasDef: VisibilityOwner, NameOwner, TypeParamsOwner, AttrsOwner, DocCommentsOwner, TypeBoundsOwner { |
390 | DefaultKw, | ||
391 | TypeKw, | ||
392 | Eq, | ||
358 | TypeRef, | 393 | TypeRef, |
394 | Semi | ||
359 | } | 395 | } |
360 | 396 | ||
361 | struct ImplDef: TypeParamsOwner, AttrsOwner { | 397 | struct ImplDef: TypeParamsOwner, AttrsOwner { |
398 | DefaultKw, | ||
399 | ConstKw, | ||
400 | UnsafeKw, | ||
401 | ImplKw, | ||
402 | Excl, | ||
403 | ForKw, | ||
362 | ItemList, | 404 | ItemList, |
363 | } | 405 | } |
364 | 406 | ||
365 | struct ParenType { TypeRef } | 407 | struct ParenType { LParen, TypeRef, RParen } |
366 | struct TupleType { fields: [TypeRef] } | 408 | struct TupleType { LParen, fields: [TypeRef], RParen } |
367 | struct NeverType { } | 409 | struct NeverType { Excl } |
368 | struct PathType { Path } | 410 | struct PathType { Path } |
369 | struct PointerType { TypeRef } | 411 | struct PointerType { Star, ConstKw, MutKw, TypeRef } |
370 | struct ArrayType { TypeRef, Expr } | 412 | struct ArrayType { LBrack, TypeRef, Semi, Expr, RBrack } |
371 | struct SliceType { TypeRef } | 413 | struct SliceType { LBrack, TypeRef, RBrack } |
372 | struct ReferenceType { TypeRef } | 414 | struct ReferenceType { Amp, Lifetime, MutKw, TypeRef } |
373 | struct PlaceholderType { } | 415 | struct PlaceholderType { Underscore } |
374 | struct FnPointerType { ParamList, RetType } | 416 | struct FnPointerType { Abi, UnsafeKw, FnKw, ParamList, RetType } |
375 | struct ForType { TypeRef } | 417 | struct ForType { ForKw, TypeParamList, TypeRef } |
376 | struct ImplTraitType: TypeBoundsOwner {} | 418 | struct ImplTraitType: TypeBoundsOwner { ImplKw } |
377 | struct DynTraitType: TypeBoundsOwner {} | 419 | struct DynTraitType: TypeBoundsOwner { DynKw } |
378 | 420 | ||
379 | struct TupleExpr { exprs: [Expr] } | 421 | struct TupleExpr: AttrsOwner { LParen, exprs: [Expr], RParen } |
380 | struct ArrayExpr { exprs: [Expr] } | 422 | struct ArrayExpr: AttrsOwner { LBrack, exprs: [Expr], Semi, RBrack } |
381 | struct ParenExpr { Expr } | 423 | struct ParenExpr: AttrsOwner { LParen, Expr, RParen } |
382 | struct PathExpr { Path } | 424 | struct PathExpr { Path } |
383 | struct LambdaExpr { | 425 | struct LambdaExpr: AttrsOwner { |
426 | StaticKw, | ||
427 | AsyncKw, | ||
428 | MoveKw, | ||
384 | ParamList, | 429 | ParamList, |
385 | RetType, | 430 | RetType, |
386 | body: Expr, | 431 | body: Expr, |
387 | } | 432 | } |
388 | struct IfExpr { Condition } | 433 | struct IfExpr: AttrsOwner { IfKw, Condition } |
389 | struct LoopExpr: LoopBodyOwner { } | 434 | struct LoopExpr: AttrsOwner, LoopBodyOwner { LoopKw } |
390 | struct TryBlockExpr { body: BlockExpr } | 435 | struct TryBlockExpr: AttrsOwner { TryKw, body: BlockExpr } |
391 | struct ForExpr: LoopBodyOwner { | 436 | struct ForExpr: AttrsOwner, LoopBodyOwner { |
437 | ForKw, | ||
392 | Pat, | 438 | Pat, |
439 | InKw, | ||
393 | iterable: Expr, | 440 | iterable: Expr, |
394 | } | 441 | } |
395 | struct WhileExpr: LoopBodyOwner { Condition } | 442 | struct WhileExpr: AttrsOwner, LoopBodyOwner { WhileKw, Condition } |
396 | struct ContinueExpr {} | 443 | struct ContinueExpr: AttrsOwner { ContinueKw, Lifetime } |
397 | struct BreakExpr { Expr } | 444 | struct BreakExpr: AttrsOwner { BreakKw, Lifetime, Expr } |
398 | struct Label {} | 445 | struct Label { Lifetime } |
399 | struct BlockExpr { Block } | 446 | struct BlockExpr: AttrsOwner { Label, UnsafeKw, Block } |
400 | struct ReturnExpr { Expr } | 447 | struct ReturnExpr: AttrsOwner { Expr } |
401 | struct CallExpr: ArgListOwner { Expr } | 448 | struct CallExpr: ArgListOwner { Expr } |
402 | struct MethodCallExpr: ArgListOwner { | 449 | struct MethodCallExpr: AttrsOwner, ArgListOwner { |
403 | Expr, NameRef, TypeArgList, | 450 | Expr, Dot, NameRef, TypeArgList, |
404 | } | 451 | } |
405 | struct IndexExpr {} | 452 | struct IndexExpr: AttrsOwner { LBrack, RBrack } |
406 | struct FieldExpr { Expr, NameRef } | 453 | struct FieldExpr: AttrsOwner { Expr, Dot, NameRef } |
407 | struct AwaitExpr { Expr } | 454 | struct AwaitExpr: AttrsOwner { Expr, Dot, AwaitKw } |
408 | struct TryExpr { Expr } | 455 | struct TryExpr: AttrsOwner { TryKw, Expr } |
409 | struct CastExpr { Expr, TypeRef } | 456 | struct CastExpr: AttrsOwner { Expr, AsKw, TypeRef } |
410 | struct RefExpr { Expr } | 457 | struct RefExpr: AttrsOwner { Amp, RawKw, MutKw, Expr } |
411 | struct PrefixExpr { Expr } | 458 | struct PrefixExpr: AttrsOwner { PrefixOp, Expr } |
412 | struct BoxExpr { Expr } | 459 | struct BoxExpr: AttrsOwner { BoxKw, Expr } |
413 | struct RangeExpr {} | 460 | struct RangeExpr: AttrsOwner { RangeOp } |
414 | struct BinExpr {} | 461 | struct BinExpr: AttrsOwner { BinOp } |
415 | struct Literal {} | 462 | struct Literal { LiteralToken } |
416 | 463 | ||
417 | struct MatchExpr { Expr, MatchArmList } | 464 | struct MatchExpr: AttrsOwner { MatchKw, Expr, MatchArmList } |
418 | struct MatchArmList: AttrsOwner { arms: [MatchArm] } | 465 | struct MatchArmList: AttrsOwner { LCurly, arms: [MatchArm], RCurly } |
419 | struct MatchArm: AttrsOwner { | 466 | struct MatchArm: AttrsOwner { |
420 | pat: Pat, | 467 | pat: Pat, |
421 | guard: MatchGuard, | 468 | guard: MatchGuard, |
469 | FatArrow, | ||
422 | Expr, | 470 | Expr, |
423 | } | 471 | } |
424 | struct MatchGuard { Expr } | 472 | struct MatchGuard { IfKw, Expr } |
425 | 473 | ||
426 | struct RecordLit { Path, RecordFieldList } | 474 | struct RecordLit { Path, RecordFieldList} |
427 | struct RecordFieldList { | 475 | struct RecordFieldList { |
476 | LCurly, | ||
428 | fields: [RecordField], | 477 | fields: [RecordField], |
478 | Dotdot, | ||
429 | spread: Expr, | 479 | spread: Expr, |
480 | RCurly | ||
430 | } | 481 | } |
431 | struct RecordField { NameRef, Expr } | 482 | struct RecordField: AttrsOwner { NameRef, Colon, Expr } |
432 | 483 | ||
433 | struct OrPat { pats: [Pat] } | 484 | struct OrPat { pats: [Pat] } |
434 | struct ParenPat { Pat } | 485 | struct ParenPat { LParen, Pat, RParen } |
435 | struct RefPat { Pat } | 486 | struct RefPat { Amp, MutKw, Pat } |
436 | struct BoxPat { Pat } | 487 | struct BoxPat { BoxKw, Pat } |
437 | struct BindPat: NameOwner { Pat } | 488 | struct BindPat: AttrsOwner, NameOwner { RefKw, MutKw, At, Pat } |
438 | struct PlaceholderPat { } | 489 | struct PlaceholderPat { Underscore } |
439 | struct DotDotPat { } | 490 | struct DotDotPat { Dotdot } |
440 | struct PathPat { Path } | 491 | struct PathPat { Path } |
441 | struct SlicePat { args: [Pat] } | 492 | struct SlicePat { LBrack, args: [Pat], RBrack } |
442 | struct RangePat {} | 493 | struct RangePat { RangeSeparator } |
443 | struct LiteralPat { Literal } | 494 | struct LiteralPat { Literal } |
444 | struct MacroPat { MacroCall } | 495 | struct MacroPat { MacroCall } |
445 | 496 | ||
446 | struct RecordPat { RecordFieldPatList, Path } | 497 | struct RecordPat { RecordFieldPatList, Path } |
447 | struct RecordFieldPatList { | 498 | struct RecordFieldPatList { |
499 | LCurly, | ||
500 | pats: [RecordInnerPat], | ||
448 | record_field_pats: [RecordFieldPat], | 501 | record_field_pats: [RecordFieldPat], |
449 | bind_pats: [BindPat], | 502 | bind_pats: [BindPat], |
503 | Dotdot, | ||
504 | RCurly | ||
450 | } | 505 | } |
451 | struct RecordFieldPat: NameOwner { Pat } | 506 | struct RecordFieldPat: AttrsOwner, NameOwner { Colon, Pat } |
452 | 507 | ||
453 | struct TupleStructPat { Path, args: [Pat] } | 508 | struct TupleStructPat { Path, LParen, args: [Pat], RParen } |
454 | struct TuplePat { args: [Pat] } | 509 | struct TuplePat { LParen, args: [Pat], RParen } |
455 | 510 | ||
456 | struct Visibility {} | 511 | struct Visibility { PubKw, SuperKw, SelfKw, CrateKw } |
457 | struct Name {} | 512 | struct Name { Ident } |
458 | struct NameRef {} | 513 | struct NameRef { NameRefToken } |
459 | 514 | ||
460 | struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner { | 515 | struct MacroCall: NameOwner, AttrsOwner,DocCommentsOwner { |
461 | TokenTree, Path | 516 | Path, Excl, TokenTree, Semi |
462 | } | 517 | } |
463 | struct Attr { Path, input: AttrInput } | 518 | struct Attr { Pound, Excl, LBrack, Path, Eq, input: AttrInput, RBrack } |
464 | struct TokenTree {} | 519 | struct TokenTree {} |
465 | struct TypeParamList { | 520 | struct TypeParamList { |
521 | LAngle, | ||
522 | generic_params: [GenericParam], | ||
466 | type_params: [TypeParam], | 523 | type_params: [TypeParam], |
467 | lifetime_params: [LifetimeParam], | 524 | lifetime_params: [LifetimeParam], |
525 | const_params: [ConstParam], | ||
526 | RAngle | ||
468 | } | 527 | } |
469 | struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { | 528 | struct TypeParam: NameOwner, AttrsOwner, TypeBoundsOwner { |
529 | Eq, | ||
470 | default_type: TypeRef, | 530 | default_type: TypeRef, |
471 | } | 531 | } |
472 | struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { | 532 | struct ConstParam: NameOwner, AttrsOwner, TypeAscriptionOwner { |
533 | Eq, | ||
473 | default_val: Expr, | 534 | default_val: Expr, |
474 | } | 535 | } |
475 | struct LifetimeParam: AttrsOwner { } | 536 | struct LifetimeParam: AttrsOwner { Lifetime} |
476 | struct TypeBound { TypeRef} | 537 | struct TypeBound { Lifetime, /* Question, */ ConstKw, /* Question, */ TypeRef} |
477 | struct TypeBoundList { bounds: [TypeBound] } | 538 | struct TypeBoundList { bounds: [TypeBound] } |
478 | struct WherePred: TypeBoundsOwner { TypeRef } | 539 | struct WherePred: TypeBoundsOwner { Lifetime, TypeRef } |
479 | struct WhereClause { predicates: [WherePred] } | 540 | struct WhereClause { WhereKw, predicates: [WherePred] } |
480 | struct ExprStmt { Expr } | 541 | struct Abi { String } |
481 | struct LetStmt: TypeAscriptionOwner { | 542 | struct ExprStmt: AttrsOwner { Expr, Semi } |
543 | struct LetStmt: AttrsOwner, TypeAscriptionOwner { | ||
544 | LetKw, | ||
482 | Pat, | 545 | Pat, |
546 | Eq, | ||
483 | initializer: Expr, | 547 | initializer: Expr, |
548 | Semi, | ||
484 | } | 549 | } |
485 | struct Condition { Pat, Expr } | 550 | struct Condition { LetKw, Pat, Eq, Expr } |
486 | struct Block: AttrsOwner, ModuleItemOwner { | 551 | struct Block: AttrsOwner, ModuleItemOwner { |
552 | LCurly, | ||
487 | statements: [Stmt], | 553 | statements: [Stmt], |
488 | Expr, | 554 | Expr, |
555 | RCurly, | ||
489 | } | 556 | } |
490 | struct ParamList { | 557 | struct ParamList { |
558 | LParen, | ||
491 | SelfParam, | 559 | SelfParam, |
492 | params: [Param], | 560 | params: [Param], |
561 | RParen | ||
493 | } | 562 | } |
494 | struct SelfParam: TypeAscriptionOwner, AttrsOwner { } | 563 | struct SelfParam: TypeAscriptionOwner, AttrsOwner { Amp, Lifetime, SelfKw } |
495 | struct Param: TypeAscriptionOwner, AttrsOwner { | 564 | struct Param: TypeAscriptionOwner, AttrsOwner { |
496 | Pat, | 565 | Pat, |
566 | Dotdotdot | ||
497 | } | 567 | } |
498 | struct UseItem: AttrsOwner, VisibilityOwner { | 568 | struct UseItem: AttrsOwner, VisibilityOwner { |
569 | UseKw, | ||
499 | UseTree, | 570 | UseTree, |
500 | } | 571 | } |
501 | struct UseTree { | 572 | struct UseTree { |
502 | Path, UseTreeList, Alias | 573 | Path, Star, UseTreeList, Alias |
503 | } | 574 | } |
504 | struct Alias: NameOwner { } | 575 | struct Alias: NameOwner { AsKw } |
505 | struct UseTreeList { use_trees: [UseTree] } | 576 | struct UseTreeList { LCurly, use_trees: [UseTree], RCurly } |
506 | struct ExternCrateItem: AttrsOwner, VisibilityOwner { | 577 | struct ExternCrateItem: AttrsOwner, VisibilityOwner { |
507 | NameRef, Alias, | 578 | ExternKw, CrateKw, NameRef, Alias, |
508 | } | 579 | } |
509 | struct ArgList { | 580 | struct ArgList { |
581 | LParen, | ||
510 | args: [Expr], | 582 | args: [Expr], |
583 | RParen | ||
511 | } | 584 | } |
512 | struct Path { | 585 | struct Path { |
513 | segment: PathSegment, | 586 | segment: PathSegment, |
514 | qualifier: Path, | 587 | qualifier: Path, |
515 | } | 588 | } |
516 | struct PathSegment { | 589 | struct PathSegment { |
517 | NameRef, TypeArgList, ParamList, RetType, PathType, | 590 | Coloncolon, LAngle, NameRef, TypeArgList, ParamList, RetType, PathType, RAngle |
518 | } | 591 | } |
519 | struct TypeArgList { | 592 | struct TypeArgList { |
593 | Coloncolon, | ||
594 | LAngle, | ||
595 | generic_args: [GenericArg], | ||
520 | type_args: [TypeArg], | 596 | type_args: [TypeArg], |
521 | lifetime_args: [LifetimeArg], | 597 | lifetime_args: [LifetimeArg], |
522 | assoc_type_args: [AssocTypeArg], | 598 | assoc_type_args: [AssocTypeArg], |
523 | const_arg: [ConstArg], | 599 | const_args: [ConstArg], |
600 | RAngle | ||
524 | } | 601 | } |
525 | struct TypeArg { TypeRef } | 602 | struct TypeArg { TypeRef } |
526 | struct AssocTypeArg { NameRef, TypeRef } | 603 | struct AssocTypeArg : TypeBoundsOwner { NameRef, Eq, TypeRef } |
527 | struct LifetimeArg {} | 604 | struct LifetimeArg { Lifetime } |
528 | struct ConstArg { Literal, BlockExpr } | 605 | struct ConstArg { Literal, Eq, BlockExpr } |
529 | 606 | ||
530 | struct MacroItems: ModuleItemOwner, FnDefOwner { } | 607 | struct MacroItems: ModuleItemOwner, FnDefOwner { } |
531 | 608 | ||
@@ -533,12 +610,44 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
533 | statements: [Stmt], | 610 | statements: [Stmt], |
534 | Expr, | 611 | Expr, |
535 | } | 612 | } |
613 | |||
614 | struct ExternItemList: FnDefOwner, ModuleItemOwner { | ||
615 | LCurly, | ||
616 | extern_items: [ExternItem], | ||
617 | RCurly | ||
618 | } | ||
619 | |||
620 | struct ExternBlock { | ||
621 | Abi, | ||
622 | ExternItemList | ||
623 | } | ||
624 | |||
625 | struct MetaItem { | ||
626 | Path, Eq, AttrInput, nested_meta_items: [MetaItem] | ||
627 | } | ||
628 | |||
629 | struct MacroDef { | ||
630 | Name, TokenTree | ||
631 | } | ||
536 | }, | 632 | }, |
537 | enums: &ast_enums! { | 633 | enums: &ast_enums! { |
538 | enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner { | 634 | enum NominalDef: NameOwner, TypeParamsOwner, AttrsOwner { |
539 | StructDef, EnumDef, UnionDef, | 635 | StructDef, EnumDef, UnionDef, |
540 | } | 636 | } |
541 | 637 | ||
638 | enum GenericParam { | ||
639 | LifetimeParam, | ||
640 | TypeParam, | ||
641 | ConstParam | ||
642 | } | ||
643 | |||
644 | enum GenericArg { | ||
645 | LifetimeArg, | ||
646 | TypeArg, | ||
647 | ConstArg, | ||
648 | AssocTypeArg | ||
649 | } | ||
650 | |||
542 | enum TypeRef { | 651 | enum TypeRef { |
543 | ParenType, | 652 | ParenType, |
544 | TupleType, | 653 | TupleType, |
@@ -555,7 +664,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
555 | DynTraitType, | 664 | DynTraitType, |
556 | } | 665 | } |
557 | 666 | ||
558 | enum ModuleItem: AttrsOwner, VisibilityOwner { | 667 | enum ModuleItem: NameOwner, AttrsOwner, VisibilityOwner { |
559 | StructDef, | 668 | StructDef, |
560 | UnionDef, | 669 | UnionDef, |
561 | EnumDef, | 670 | EnumDef, |
@@ -569,13 +678,20 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
569 | StaticDef, | 678 | StaticDef, |
570 | Module, | 679 | Module, |
571 | MacroCall, | 680 | MacroCall, |
681 | ExternBlock | ||
572 | } | 682 | } |
573 | 683 | ||
574 | enum ImplItem: AttrsOwner { | 684 | /* impl blocks can also contain MacroCall */ |
575 | FnDef, TypeAliasDef, ConstDef, | 685 | enum ImplItem: NameOwner, AttrsOwner { |
686 | FnDef, TypeAliasDef, ConstDef | ||
576 | } | 687 | } |
577 | 688 | ||
578 | enum Expr { | 689 | /* extern blocks can also contain MacroCall */ |
690 | enum ExternItem: NameOwner, AttrsOwner, VisibilityOwner { | ||
691 | FnDef, StaticDef | ||
692 | } | ||
693 | |||
694 | enum Expr: AttrsOwner { | ||
579 | TupleExpr, | 695 | TupleExpr, |
580 | ArrayExpr, | 696 | ArrayExpr, |
581 | ParenExpr, | 697 | ParenExpr, |
@@ -627,7 +743,88 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
627 | MacroPat, | 743 | MacroPat, |
628 | } | 744 | } |
629 | 745 | ||
746 | enum RecordInnerPat { | ||
747 | RecordFieldPat, | ||
748 | BindPat | ||
749 | } | ||
750 | |||
630 | enum AttrInput { Literal, TokenTree } | 751 | enum AttrInput { Literal, TokenTree } |
631 | enum Stmt { ExprStmt, LetStmt } | 752 | enum Stmt { |
753 | LetStmt, | ||
754 | ExprStmt, | ||
755 | // macro calls are parsed as expression statements */ | ||
756 | } | ||
757 | |||
758 | enum FieldDefList { | ||
759 | RecordFieldDefList, | ||
760 | TupleFieldDefList, | ||
761 | } | ||
762 | }, | ||
763 | |||
764 | token_enums: &ast_enums! { | ||
765 | enum LeftDelimiter { LParen, LBrack, LCurly } | ||
766 | enum RightDelimiter { RParen, RBrack, RCurly } | ||
767 | enum RangeSeparator { Dotdot, Dotdotdot, Dotdoteq} | ||
768 | |||
769 | enum BinOp { | ||
770 | Pipepipe, | ||
771 | Ampamp, | ||
772 | Eqeq, | ||
773 | Neq, | ||
774 | Lteq, | ||
775 | Gteq, | ||
776 | LAngle, | ||
777 | RAngle, | ||
778 | Plus, | ||
779 | Star, | ||
780 | Minus, | ||
781 | Slash, | ||
782 | Percent, | ||
783 | Shl, | ||
784 | Shr, | ||
785 | Caret, | ||
786 | Pipe, | ||
787 | Amp, | ||
788 | Eq, | ||
789 | Pluseq, | ||
790 | Slasheq, | ||
791 | Stareq, | ||
792 | Percenteq, | ||
793 | Shreq, | ||
794 | Shleq, | ||
795 | Minuseq, | ||
796 | Pipeeq, | ||
797 | Ampeq, | ||
798 | Careteq, | ||
799 | } | ||
800 | |||
801 | enum PrefixOp { | ||
802 | Minus, | ||
803 | Excl, | ||
804 | Star | ||
805 | } | ||
806 | |||
807 | enum RangeOp { | ||
808 | Dotdot, | ||
809 | Dotdoteq | ||
810 | } | ||
811 | |||
812 | enum LiteralToken { | ||
813 | IntNumber, | ||
814 | FloatNumber, | ||
815 | String, | ||
816 | RawString, | ||
817 | TrueKw, | ||
818 | FalseKw, | ||
819 | ByteString, | ||
820 | RawByteString, | ||
821 | Char, | ||
822 | Byte | ||
823 | } | ||
824 | |||
825 | enum NameRefToken { | ||
826 | Ident, | ||
827 | IntNumber | ||
828 | } | ||
632 | }, | 829 | }, |
633 | }; | 830 | }; |
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index a53d57335..678b40133 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs | |||
@@ -22,8 +22,9 @@ const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; | |||
22 | const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok"; | 22 | const OK_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/ok"; |
23 | const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err"; | 23 | const ERR_INLINE_TESTS_DIR: &str = "crates/ra_syntax/test_data/parser/inline/err"; |
24 | 24 | ||
25 | pub const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs"; | 25 | const SYNTAX_KINDS: &str = "crates/ra_parser/src/syntax_kind/generated.rs"; |
26 | pub const AST: &str = "crates/ra_syntax/src/ast/generated.rs"; | 26 | const AST_NODES: &str = "crates/ra_syntax/src/ast/generated/nodes.rs"; |
27 | const AST_TOKENS: &str = "crates/ra_syntax/src/ast/generated/tokens.rs"; | ||
27 | 28 | ||
28 | const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; | 29 | const ASSISTS_DIR: &str = "crates/ra_assists/src/handlers"; |
29 | const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs"; | 30 | const ASSISTS_TESTS: &str = "crates/ra_assists/src/doc_tests/generated.rs"; |
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 32afd47bc..b5594e3a9 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -3,6 +3,11 @@ | |||
3 | //! Specifically, it generates the `SyntaxKind` enum and a number of newtype | 3 | //! Specifically, it generates the `SyntaxKind` enum and a number of newtype |
4 | //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. | 4 | //! wrappers around `SyntaxNode` which implement `ra_syntax::AstNode`. |
5 | 5 | ||
6 | use std::{ | ||
7 | borrow::Cow, | ||
8 | collections::{BTreeSet, HashSet}, | ||
9 | }; | ||
10 | |||
6 | use proc_macro2::{Punct, Spacing}; | 11 | use proc_macro2::{Punct, Spacing}; |
7 | use quote::{format_ident, quote}; | 12 | use quote::{format_ident, quote}; |
8 | 13 | ||
@@ -17,14 +22,161 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { | |||
17 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; | 22 | let syntax_kinds = generate_syntax_kinds(KINDS_SRC)?; |
18 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; | 23 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; |
19 | 24 | ||
20 | let ast_file = project_root().join(codegen::AST); | 25 | let ast_nodes_file = project_root().join(codegen::AST_NODES); |
21 | let ast = generate_ast(AST_SRC)?; | 26 | let contents = generate_nodes(KINDS_SRC, AST_SRC)?; |
22 | update(ast_file.as_path(), &ast, mode)?; | 27 | update(ast_nodes_file.as_path(), &contents, mode)?; |
28 | |||
29 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); | ||
30 | let contents = generate_tokens(KINDS_SRC, AST_SRC)?; | ||
31 | update(ast_tokens_file.as_path(), &contents, mode)?; | ||
23 | 32 | ||
24 | Ok(()) | 33 | Ok(()) |
25 | } | 34 | } |
26 | 35 | ||
27 | fn generate_ast(grammar: AstSrc<'_>) -> Result<String> { | 36 | #[derive(Debug, Default, Clone)] |
37 | struct ElementKinds { | ||
38 | kinds: BTreeSet<proc_macro2::Ident>, | ||
39 | has_nodes: bool, | ||
40 | has_tokens: bool, | ||
41 | } | ||
42 | |||
43 | fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | ||
44 | let all_token_kinds: Vec<_> = kinds | ||
45 | .punct | ||
46 | .into_iter() | ||
47 | .map(|(_, kind)| kind) | ||
48 | .copied() | ||
49 | .map(|x| x.into()) | ||
50 | .chain( | ||
51 | kinds | ||
52 | .keywords | ||
53 | .into_iter() | ||
54 | .chain(kinds.contextual_keywords.into_iter()) | ||
55 | .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), | ||
56 | ) | ||
57 | .chain(kinds.literals.into_iter().copied().map(|x| x.into())) | ||
58 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) | ||
59 | .collect(); | ||
60 | |||
61 | let tokens = all_token_kinds.iter().map(|kind_str| { | ||
62 | let kind_str = &**kind_str; | ||
63 | let kind = format_ident!("{}", kind_str); | ||
64 | let name = format_ident!("{}", to_pascal_case(kind_str)); | ||
65 | quote! { | ||
66 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
67 | pub struct #name { | ||
68 | pub(crate) syntax: SyntaxToken, | ||
69 | } | ||
70 | |||
71 | impl std::fmt::Display for #name { | ||
72 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
73 | std::fmt::Display::fmt(&self.syntax, f) | ||
74 | } | ||
75 | } | ||
76 | |||
77 | impl AstToken for #name { | ||
78 | fn can_cast(kind: SyntaxKind) -> bool { kind == #kind } | ||
79 | fn cast(syntax: SyntaxToken) -> Option<Self> { | ||
80 | if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } | ||
81 | } | ||
82 | fn syntax(&self) -> &SyntaxToken { &self.syntax } | ||
83 | } | ||
84 | } | ||
85 | }); | ||
86 | |||
87 | let enums = grammar.token_enums.iter().map(|en| { | ||
88 | let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>(); | ||
89 | let name = format_ident!("{}", en.name); | ||
90 | let kinds = variants | ||
91 | .iter() | ||
92 | .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string()))) | ||
93 | .collect::<Vec<_>>(); | ||
94 | assert!(en.traits.is_empty()); | ||
95 | |||
96 | quote! { | ||
97 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
98 | pub enum #name { | ||
99 | #(#variants(#variants),)* | ||
100 | } | ||
101 | |||
102 | #( | ||
103 | impl From<#variants> for #name { | ||
104 | fn from(node: #variants) -> #name { | ||
105 | #name::#variants(node) | ||
106 | } | ||
107 | } | ||
108 | )* | ||
109 | |||
110 | impl std::fmt::Display for #name { | ||
111 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
112 | std::fmt::Display::fmt(self.syntax(), f) | ||
113 | } | ||
114 | } | ||
115 | |||
116 | impl AstToken for #name { | ||
117 | fn can_cast(kind: SyntaxKind) -> bool { | ||
118 | match kind { | ||
119 | #(#kinds)|* => true, | ||
120 | _ => false, | ||
121 | } | ||
122 | } | ||
123 | fn cast(syntax: SyntaxToken) -> Option<Self> { | ||
124 | let res = match syntax.kind() { | ||
125 | #( | ||
126 | #kinds => #name::#variants(#variants { syntax }), | ||
127 | )* | ||
128 | _ => return None, | ||
129 | }; | ||
130 | Some(res) | ||
131 | } | ||
132 | fn syntax(&self) -> &SyntaxToken { | ||
133 | match self { | ||
134 | #( | ||
135 | #name::#variants(it) => &it.syntax, | ||
136 | )* | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | }); | ||
142 | |||
143 | crate::reformat(quote! { | ||
144 | use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; | ||
145 | |||
146 | #(#tokens)* | ||
147 | #(#enums)* | ||
148 | }) | ||
149 | } | ||
150 | |||
151 | fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | ||
152 | let all_token_kinds: Vec<_> = kinds | ||
153 | .punct | ||
154 | .into_iter() | ||
155 | .map(|(_, kind)| kind) | ||
156 | .copied() | ||
157 | .map(|x| x.into()) | ||
158 | .chain( | ||
159 | kinds | ||
160 | .keywords | ||
161 | .into_iter() | ||
162 | .chain(kinds.contextual_keywords.into_iter()) | ||
163 | .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), | ||
164 | ) | ||
165 | .chain(kinds.literals.into_iter().copied().map(|x| x.into())) | ||
166 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) | ||
167 | .collect(); | ||
168 | |||
169 | let mut token_kinds = HashSet::new(); | ||
170 | for kind in &all_token_kinds { | ||
171 | let kind = &**kind; | ||
172 | let name = to_pascal_case(kind); | ||
173 | token_kinds.insert(name); | ||
174 | } | ||
175 | |||
176 | for en in grammar.token_enums { | ||
177 | token_kinds.insert(en.name.to_string()); | ||
178 | } | ||
179 | |||
28 | let nodes = grammar.nodes.iter().map(|node| { | 180 | let nodes = grammar.nodes.iter().map(|node| { |
29 | let name = format_ident!("{}", node.name); | 181 | let name = format_ident!("{}", node.name); |
30 | let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); | 182 | let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); |
@@ -42,20 +194,31 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> { | |||
42 | FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty, | 194 | FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty, |
43 | FieldSrc::Shorthand => name, | 195 | FieldSrc::Shorthand => name, |
44 | }; | 196 | }; |
197 | |||
45 | let ty = format_ident!("{}", ty); | 198 | let ty = format_ident!("{}", ty); |
46 | 199 | ||
47 | match field { | 200 | match field { |
48 | FieldSrc::Many(_) => { | 201 | FieldSrc::Many(_) => { |
49 | quote! { | 202 | quote! { |
50 | pub fn #method_name(&self) -> AstChildren<#ty> { | 203 | pub fn #method_name(&self) -> AstChildren<#ty> { |
51 | AstChildren::new(&self.syntax) | 204 | support::children(&self.syntax) |
52 | } | 205 | } |
53 | } | 206 | } |
54 | } | 207 | } |
55 | FieldSrc::Optional(_) | FieldSrc::Shorthand => { | 208 | FieldSrc::Optional(_) | FieldSrc::Shorthand => { |
56 | quote! { | 209 | let is_token = token_kinds.contains(&ty.to_string()); |
57 | pub fn #method_name(&self) -> Option<#ty> { | 210 | if is_token { |
58 | AstChildren::new(&self.syntax).next() | 211 | let method_name = format_ident!("{}_token", method_name); |
212 | quote! { | ||
213 | pub fn #method_name(&self) -> Option<#ty> { | ||
214 | support::token(&self.syntax) | ||
215 | } | ||
216 | } | ||
217 | } else { | ||
218 | quote! { | ||
219 | pub fn #method_name(&self) -> Option<#ty> { | ||
220 | support::child(&self.syntax) | ||
221 | } | ||
59 | } | 222 | } |
60 | } | 223 | } |
61 | } | 224 | } |
@@ -68,24 +231,16 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> { | |||
68 | pub(crate) syntax: SyntaxNode, | 231 | pub(crate) syntax: SyntaxNode, |
69 | } | 232 | } |
70 | 233 | ||
71 | impl std::fmt::Display for #name { | ||
72 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
73 | std::fmt::Display::fmt(self.syntax(), f) | ||
74 | } | ||
75 | } | ||
76 | |||
77 | impl AstNode for #name { | 234 | impl AstNode for #name { |
78 | fn can_cast(kind: SyntaxKind) -> bool { | 235 | fn can_cast(kind: SyntaxKind) -> bool { |
79 | match kind { | 236 | kind == #kind |
80 | #kind => true, | ||
81 | _ => false, | ||
82 | } | ||
83 | } | 237 | } |
84 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 238 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
85 | if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } | 239 | if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } |
86 | } | 240 | } |
87 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 241 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
88 | } | 242 | } |
243 | |||
89 | #(#traits)* | 244 | #(#traits)* |
90 | 245 | ||
91 | impl #name { | 246 | impl #name { |
@@ -120,12 +275,6 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> { | |||
120 | } | 275 | } |
121 | )* | 276 | )* |
122 | 277 | ||
123 | impl std::fmt::Display for #name { | ||
124 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
125 | std::fmt::Display::fmt(self.syntax(), f) | ||
126 | } | ||
127 | } | ||
128 | |||
129 | impl AstNode for #name { | 278 | impl AstNode for #name { |
130 | fn can_cast(kind: SyntaxKind) -> bool { | 279 | fn can_cast(kind: SyntaxKind) -> bool { |
131 | match kind { | 280 | match kind { |
@@ -150,18 +299,48 @@ fn generate_ast(grammar: AstSrc<'_>) -> Result<String> { | |||
150 | } | 299 | } |
151 | } | 300 | } |
152 | } | 301 | } |
302 | |||
153 | #(#traits)* | 303 | #(#traits)* |
154 | } | 304 | } |
155 | }); | 305 | }); |
156 | 306 | ||
307 | let displays = grammar | ||
308 | .enums | ||
309 | .iter() | ||
310 | .map(|it| format_ident!("{}", it.name)) | ||
311 | .chain(grammar.nodes.iter().map(|it| format_ident!("{}", it.name))) | ||
312 | .map(|name| { | ||
313 | quote! { | ||
314 | impl std::fmt::Display for #name { | ||
315 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
316 | std::fmt::Display::fmt(self.syntax(), f) | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | }); | ||
321 | |||
322 | let defined_nodes: HashSet<_> = grammar.nodes.iter().map(|node| node.name).collect(); | ||
323 | |||
324 | for node in kinds | ||
325 | .nodes | ||
326 | .iter() | ||
327 | .map(|kind| to_pascal_case(*kind)) | ||
328 | .filter(|name| !defined_nodes.contains(&**name)) | ||
329 | { | ||
330 | eprintln!("Warning: node {} not defined in ast source", node); | ||
331 | } | ||
332 | |||
157 | let ast = quote! { | 333 | let ast = quote! { |
158 | use crate::{ | 334 | use crate::{ |
159 | SyntaxNode, SyntaxKind::{self, *}, | 335 | SyntaxNode, SyntaxKind::{self, *}, |
160 | ast::{self, AstNode, AstChildren}, | 336 | ast::{self, AstNode, AstChildren, support}, |
161 | }; | 337 | }; |
162 | 338 | ||
339 | use super::tokens::*; | ||
340 | |||
163 | #(#nodes)* | 341 | #(#nodes)* |
164 | #(#enums)* | 342 | #(#enums)* |
343 | #(#displays)* | ||
165 | }; | 344 | }; |
166 | 345 | ||
167 | let pretty = crate::reformat(ast)?; | 346 | let pretty = crate::reformat(ast)?; |
@@ -282,12 +461,12 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> Result<String> { | |||
282 | 461 | ||
283 | fn to_upper_snake_case(s: &str) -> String { | 462 | fn to_upper_snake_case(s: &str) -> String { |
284 | let mut buf = String::with_capacity(s.len()); | 463 | let mut buf = String::with_capacity(s.len()); |
285 | let mut prev_is_upper = None; | 464 | let mut prev = false; |
286 | for c in s.chars() { | 465 | for c in s.chars() { |
287 | if c.is_ascii_uppercase() && prev_is_upper == Some(false) { | 466 | if c.is_ascii_uppercase() && prev { |
288 | buf.push('_') | 467 | buf.push('_') |
289 | } | 468 | } |
290 | prev_is_upper = Some(c.is_ascii_uppercase()); | 469 | prev = true; |
291 | 470 | ||
292 | buf.push(c.to_ascii_uppercase()); | 471 | buf.push(c.to_ascii_uppercase()); |
293 | } | 472 | } |
@@ -296,14 +475,30 @@ fn to_upper_snake_case(s: &str) -> String { | |||
296 | 475 | ||
297 | fn to_lower_snake_case(s: &str) -> String { | 476 | fn to_lower_snake_case(s: &str) -> String { |
298 | let mut buf = String::with_capacity(s.len()); | 477 | let mut buf = String::with_capacity(s.len()); |
299 | let mut prev_is_upper = None; | 478 | let mut prev = false; |
300 | for c in s.chars() { | 479 | for c in s.chars() { |
301 | if c.is_ascii_uppercase() && prev_is_upper == Some(false) { | 480 | if c.is_ascii_uppercase() && prev { |
302 | buf.push('_') | 481 | buf.push('_') |
303 | } | 482 | } |
304 | prev_is_upper = Some(c.is_ascii_uppercase()); | 483 | prev = true; |
305 | 484 | ||
306 | buf.push(c.to_ascii_lowercase()); | 485 | buf.push(c.to_ascii_lowercase()); |
307 | } | 486 | } |
308 | buf | 487 | buf |
309 | } | 488 | } |
489 | |||
490 | fn to_pascal_case(s: &str) -> String { | ||
491 | let mut buf = String::with_capacity(s.len()); | ||
492 | let mut prev_is_underscore = true; | ||
493 | for c in s.chars() { | ||
494 | if c == '_' { | ||
495 | prev_is_underscore = true; | ||
496 | } else if prev_is_underscore { | ||
497 | buf.push(c.to_ascii_uppercase()); | ||
498 | prev_is_underscore = false; | ||
499 | } else { | ||
500 | buf.push(c.to_ascii_lowercase()); | ||
501 | } | ||
502 | } | ||
503 | buf | ||
504 | } | ||
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 9d087daa2..ec824a518 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs | |||
@@ -67,6 +67,7 @@ fn reformat(text: impl std::fmt::Display) -> Result<String> { | |||
67 | let mut rustfmt = Command::new("rustup") | 67 | let mut rustfmt = Command::new("rustup") |
68 | .args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"]) | 68 | .args(&["run", TOOLCHAIN, "--", "rustfmt", "--config-path"]) |
69 | .arg(project_root().join("rustfmt.toml")) | 69 | .arg(project_root().join("rustfmt.toml")) |
70 | .args(&["--config", "fn_single_line=true"]) | ||
70 | .stdin(Stdio::piped()) | 71 | .stdin(Stdio::piped()) |
71 | .stdout(Stdio::piped()) | 72 | .stdout(Stdio::piped()) |
72 | .spawn()?; | 73 | .spawn()?; |