mirror of
https://github.com/github/codeql.git
synced 2026-07-31 07:22:56 +02:00
unified: Emit base types from inheritance clauses
Map a nominal type's inheritance clause (`class C: Base, Proto`, and likewise for enum/struct/protocol/extension) to `base_type` children on the `class_like_declaration`, one per inherited type. The tree-sitter path dropped these (no corpus target had a `base_type`) and the mapping matched that for parity; swift-syntax exposes the clause cleanly. Adds a focused `class-with-multiple-base-types` corpus case and updates `class-inheritance` to witness the restored base types. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1028,50 +1028,73 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
|
||||
// (swift-syntax represents `#selector`/`#keyPath` and other macro
|
||||
// expansions uniformly as a `macroExpansionExpr`).
|
||||
rule!((macroExpansionExpr) => (unsupported_node)),
|
||||
// PARITY(tree-sitter): a nominal type's `inheritanceClause` (`: Base,
|
||||
// Proto`) is not emitted as a `base_type` — the tree-sitter path drops
|
||||
// it (no corpus target has a `base_type`). swift-syntax exposes it
|
||||
// cleanly, so emitting `base_type` is a correctness improvement to make
|
||||
// once tree-sitter is retired. Each declaration keyword gets its own
|
||||
// rule; the bodies are identical but for the keyword.
|
||||
// A nominal type's `inheritanceClause` (`: Base, Proto`) becomes a list
|
||||
// of `base_type`s, one per inherited type. The tree-sitter path dropped
|
||||
// it (no corpus target had a `base_type`) and the mapping matched that
|
||||
// for parity; swift-syntax exposes it cleanly. Each declaration keyword
|
||||
// gets its own rule; the bodies are identical but for the keyword.
|
||||
// Class declaration with body containing members
|
||||
rule!(
|
||||
(classDecl classKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
|
||||
(classDecl
|
||||
classKeyword: @kind
|
||||
modifiers: _* @mods
|
||||
name: @name
|
||||
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
|
||||
memberBlock: (memberBlock members: _* @members))
|
||||
=>
|
||||
(class_like_declaration
|
||||
modifier: (modifier #{kind})
|
||||
modifier: {mods}
|
||||
name: (identifier #{name})
|
||||
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
|
||||
member: {members})
|
||||
),
|
||||
// Enum class declaration: same as a regular class but with an enum body.
|
||||
rule!(
|
||||
(enumDecl enumKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
|
||||
(enumDecl
|
||||
enumKeyword: @kind
|
||||
modifiers: _* @mods
|
||||
name: @name
|
||||
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
|
||||
memberBlock: (memberBlock members: _* @members))
|
||||
=>
|
||||
(class_like_declaration
|
||||
modifier: (modifier #{kind})
|
||||
modifier: {mods}
|
||||
name: (identifier #{name})
|
||||
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
|
||||
member: {members})
|
||||
),
|
||||
// A `struct` declaration.
|
||||
rule!(
|
||||
(structDecl structKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
|
||||
(structDecl
|
||||
structKeyword: @kind
|
||||
modifiers: _* @mods
|
||||
name: @name
|
||||
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
|
||||
memberBlock: (memberBlock members: _* @members))
|
||||
=>
|
||||
(class_like_declaration
|
||||
modifier: (modifier #{kind})
|
||||
modifier: {mods}
|
||||
name: (identifier #{name})
|
||||
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
|
||||
member: {members})
|
||||
),
|
||||
// Protocol declaration
|
||||
rule!(
|
||||
(protocolDecl protocolKeyword: @kind modifiers: _* @mods name: @name memberBlock: (memberBlock members: _* @members))
|
||||
(protocolDecl
|
||||
protocolKeyword: @kind
|
||||
modifiers: _* @mods
|
||||
name: @name
|
||||
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
|
||||
memberBlock: (memberBlock members: _* @members))
|
||||
=>
|
||||
(class_like_declaration
|
||||
modifier: (modifier #{kind})
|
||||
modifier: {mods}
|
||||
name: (identifier #{name})
|
||||
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
|
||||
member: {members})
|
||||
),
|
||||
// An `extension Foo { … }` is likewise a `class_like_declaration`, named
|
||||
@@ -1080,12 +1103,18 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
|
||||
// a `memberType`) name the declaration just like simple ones, matching the
|
||||
// old tree-sitter `user_type` behaviour.
|
||||
rule!(
|
||||
(extensionDecl extensionKeyword: @kind modifiers: _* @mods extendedType: @@name memberBlock: (memberBlock members: _* @members))
|
||||
(extensionDecl
|
||||
extensionKeyword: @kind
|
||||
modifiers: _* @mods
|
||||
extendedType: @@name
|
||||
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
|
||||
memberBlock: (memberBlock members: _* @members))
|
||||
=>
|
||||
(class_like_declaration
|
||||
modifier: (modifier #{kind})
|
||||
modifier: {mods}
|
||||
name: (identifier #{name})
|
||||
base_type: {bases.into_iter().map(|ty| tree!((base_type type: {ty})))}
|
||||
member: {members})
|
||||
),
|
||||
// A member of a type declaration unwraps to the contained declaration.
|
||||
|
||||
@@ -35,3 +35,8 @@ top_level
|
||||
class_like_declaration
|
||||
modifier: modifier "class"
|
||||
name: identifier "Dog"
|
||||
base_type:
|
||||
base_type
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Animal"
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
class Button: Control, Drawable {}
|
||||
|
||||
---
|
||||
|
||||
sourceFile
|
||||
endOfFileToken: endOfFile
|
||||
statements:
|
||||
codeBlockItem
|
||||
item:
|
||||
classDecl
|
||||
attributes:
|
||||
name: identifier "Button"
|
||||
inheritanceClause:
|
||||
inheritanceClause
|
||||
colon: :
|
||||
inheritedTypes:
|
||||
inheritedType
|
||||
trailingComma: ,
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Control"
|
||||
inheritedType
|
||||
type:
|
||||
identifierType
|
||||
name: identifier "Drawable"
|
||||
memberBlock:
|
||||
memberBlock
|
||||
leftBrace: {
|
||||
rightBrace: }
|
||||
members:
|
||||
modifiers:
|
||||
classKeyword: class
|
||||
|
||||
---
|
||||
|
||||
top_level
|
||||
body:
|
||||
block
|
||||
stmt:
|
||||
class_like_declaration
|
||||
modifier: modifier "class"
|
||||
name: identifier "Button"
|
||||
base_type:
|
||||
base_type
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Control"
|
||||
base_type
|
||||
type:
|
||||
named_type_expr
|
||||
name: identifier "Drawable"
|
||||
@@ -0,0 +1 @@
|
||||
class Button: Control, Drawable {}
|
||||
Reference in New Issue
Block a user