Skip to content

Commit d92e57c

Browse files
authored
Merge pull request #22680 from github/tausbn/unified-distinguish-unhandled-from-unsupported-nodes
Unified: Distinguish between unsupported and unhandled nodes
2 parents 5de6283 + ebac209 commit d92e57c

4 files changed

Lines changed: 102 additions & 48 deletions

File tree

‎unified/extractor/ast_types.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ supertypes:
3434
- switch_expr
3535
- unresolved_operator_sequence
3636
- unsupported_node
37+
- unhandled_node
3738
- or_pattern
3839
- conditional_pattern
3940
- bulk_importing_pattern
@@ -84,6 +85,7 @@ supertypes:
8485
- type_alias_declaration
8586
- associated_type_declaration
8687
- unsupported_node
88+
- unhandled_node
8789
type_constraint:
8890
- equality_type_constraint
8991
- bound_type_constraint
@@ -421,6 +423,9 @@ named:
421423
# A node that we don't yet translate
422424
unsupported_node:
423425

426+
# A node kind that has no explicit translation or unsupported classification
427+
unhandled_node:
428+
424429
infix_operator:
425430

426431
prefix_operator:

‎unified/extractor/src/languages/swift/swift.rs‎

Lines changed: 85 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
129129
vec![
130130
// ---- Top-level ----
131131
// These rules translate the swift-syntax AST (camelCase kind names),
132-
// produced by the sibling `adapter` module from the `swift-syntax-parse`
133-
// binary's JSON. Anything unmatched falls through to the
134-
// `unsupported_node` fallback at the end.
132+
// produced by the sibling `adapter` module from swift-syntax JSON.
133+
// Known kinds without dedicated rules become `unsupported_node`;
134+
// genuinely unknown kinds become `unhandled_node`.
135135
//
136136
// `sourceFile` holds its top-level statements in an (elided)
137137
// `statements` collection; each element is a `codeBlockItem` wrapping
@@ -198,13 +198,13 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
198198
=>
199199
(unsupported_node)
200200
),
201-
rule!((declReferenceExpr baseName: (identifier) @name) => expr {
201+
rule!((declReferenceExpr baseName: (identifier) @@name) => expr {
202202
tree!((identifier #{name}))
203203
}),
204204
// A bare name reference (`x`), and an operator used as a value (`+` in
205205
// `reduce(0, +)`), are both `declReferenceExpr`; its `baseName` is the
206206
// referenced identifier / operator symbol.
207-
rule!((declReferenceExpr baseName: @name) => (identifier #{name})),
207+
rule!((declReferenceExpr baseName: @@name) => (identifier #{name})),
208208
// A discard `_` used as an expression — e.g. the target of a discarding
209209
// assignment `_ = x`. swift-syntax models it as a `discardAssignmentExpr`.
210210
rule!((discardAssignmentExpr wildcard: @@w) => (ignore_pattern #{w})),
@@ -215,7 +215,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
215215
// `generic_type_expr`, so we map it directly to that shape.
216216
rule!(
217217
(genericSpecializationExpr
218-
expression: (declReferenceExpr baseName: @name)
218+
expression: (declReferenceExpr baseName: @@name)
219219
genericArgumentClause: (genericArgumentClause arguments: (genericArgument argument: @args)*))
220220
=>
221221
(generic_type_expr
@@ -230,7 +230,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
230230
// A `binaryOperatorExpr` wraps the operator token; unwrap it to the
231231
// operator leaf. Used by `infixOperatorExpr` (folded) and `sequenceExpr`
232232
// (unresolved).
233-
rule!((binaryOperatorExpr operator: @op) => (infix_operator #{op})),
233+
rule!((binaryOperatorExpr operator: @@op) => (infix_operator #{op})),
234234
// A `binaryOperator`-based `infixOperatorExpr` represents both ordinary
235235
// binary applications (`a + b`) and compound assignments (`x += y`).
236236
// Both have the same target AST shape; the QL library distinguishes
@@ -276,7 +276,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
276276
// infix operators, rather than guessing a structure.
277277
rule!((sequenceExpr elements: _* @els) => (unresolved_operator_sequence element: {els})),
278278
// Prefix unary operators (`!a`, `-x`).
279-
rule!((prefixOperatorExpr operator: @op expression: @operand) => (unary_expr operator: (prefix_operator #{op}) operand: {operand})),
279+
rule!((prefixOperatorExpr operator: @@op expression: @operand) => (unary_expr operator: (prefix_operator #{op}) operand: {operand})),
280280
// A parenthesised expression has a single tuple element; elide the
281281
// grouping and preserve the expression itself. Actual tuple literals
282282
// retain their translated labeled elements as `argument` children.
@@ -468,7 +468,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
468468
// `chained_declaration` tag.
469469
rule!(
470470
(enumCaseElement
471-
name: @name
471+
name: @@name
472472
parameterClause: (enumCaseParameterClause parameters: _* @params) @@clause)
473473
=>
474474
class_like_declaration {
@@ -486,7 +486,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
486486
}
487487
),
488488
rule!(
489-
(enumCaseElement name: @name rawValue: (initializerClause value: @val))
489+
(enumCaseElement name: @@name rawValue: (initializerClause value: @val))
490490
=>
491491
(variable_declaration
492492
modifier: {ctx.outer_modifiers.clone()}
@@ -496,7 +496,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
496496
value: {val})
497497
),
498498
rule!(
499-
(enumCaseElement name: @name)
499+
(enumCaseElement name: @@name)
500500
=>
501501
(variable_declaration
502502
modifier: {ctx.outer_modifiers.clone()}
@@ -526,7 +526,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
526526
),
527527
// `identifierPattern` wraps a single identifier token.
528528
rule!(
529-
(identifierPattern identifier: @name)
529+
(identifierPattern identifier: @@name)
530530
=>
531531
(identifier #{name})
532532
),
@@ -574,7 +574,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
574574
rule!(
575575
(functionDecl
576576
modifiers: _* @mods
577-
name: @name
577+
name: @@name
578578
genericParameterClause: (genericParameterClause parameters: _* @type_params)?
579579
signature: (functionSignature
580580
parameterClause: (functionParameterClause parameters: _* @params)
@@ -592,7 +592,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
592592
rule!(
593593
(functionDecl
594594
modifiers: _* @mods
595-
name: @name
595+
name: @@name
596596
genericParameterClause: (genericParameterClause parameters: _* @type_params)?
597597
signature: (functionSignature
598598
parameterClause: (functionParameterClause parameters: _* @params)
@@ -715,7 +715,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
715715
(memberAccessExpr
716716
base: (arrayExpr
717717
elements: (arrayElement expression: (genericSpecializationExpr) @element)) @@array
718-
declName: (declReferenceExpr baseName: @member))
718+
declName: (declReferenceExpr baseName: @@member))
719719
=>
720720
member_access_expr {
721721
let base = tree_at!(
@@ -731,12 +731,12 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
731731
}
732732
),
733733
rule!(
734-
(memberAccessExpr base: @base declName: (declReferenceExpr baseName: @member))
734+
(memberAccessExpr base: @base declName: (declReferenceExpr baseName: @@member))
735735
=>
736736
(member_access_expr base: {base} member_name_node: (identifier #{member}))
737737
),
738738
rule!(
739-
(memberAccessExpr period: @dot declName: (declReferenceExpr baseName: @member))
739+
(memberAccessExpr period: @@dot declName: (declReferenceExpr baseName: @@member))
740740
=>
741741
(member_access_expr base: (inferred_type_expr #{dot}) member_name_node: (identifier #{member}))
742742
),
@@ -790,14 +790,14 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
790790
// A closure parameter (`x: Int`, or just `x`). Unlike a function
791791
// parameter it has no external label; the type is optional.
792792
rule!(
793-
(closureParameter firstName: @name type: _? @ty)
793+
(closureParameter firstName: @@name type: _? @ty)
794794
=>
795795
(parameter pattern: (identifier #{name}) type: {ty})
796796
),
797797
// A shorthand closure parameter (`x` in `{ x, y in … }`): a bare name
798798
// with no parentheses and no type.
799799
rule!(
800-
(closureShorthandParameter name: @name)
800+
(closureShorthandParameter name: @@name)
801801
=>
802802
(parameter pattern: (identifier #{name}))
803803
),
@@ -872,7 +872,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
872872
rule!(
873873
(optionalBindingCondition
874874
bindingSpecifier: @@spec
875-
pattern: (identifierPattern identifier: @name)
875+
pattern: (identifierPattern identifier: @@name)
876876
initializer: (initializerClause value: @val))
877877
=>
878878
(pattern_guard_expr
@@ -886,7 +886,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
886886
rule!(
887887
(optionalBindingCondition
888888
bindingSpecifier: @@spec
889-
pattern: (identifierPattern identifier: @name))
889+
pattern: (identifierPattern identifier: @@name))
890890
=>
891891
(pattern_guard_expr
892892
value: (identifier #{name})
@@ -1091,7 +1091,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
10911091
rule!((declModifier) @m => (modifier #{m})),
10921092
// Preserve the `super` keyword as a dedicated expression, normally used
10931093
// as the base of a member access (`super.foo`).
1094-
rule!((superExpr superKeyword: @keyword) => (super_expr #{keyword})),
1094+
rule!((superExpr superKeyword: @@keyword) => (super_expr #{keyword})),
10951095
// Type expressions. A generic type applied with explicit arguments
10961096
// (`Set<Int>`) becomes a `generic_type_expr` whose `base` is the type
10971097
// name and whose `type_argument`s are the (structured) arguments — the
@@ -1213,9 +1213,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12131213
// Class declaration with body containing members
12141214
rule!(
12151215
(classDecl
1216-
classKeyword: @kind
1216+
classKeyword: @@kind
12171217
modifiers: _* @mods
1218-
name: @name
1218+
name: @@name
12191219
genericParameterClause: (genericParameterClause
12201220
parameters: _* @params
12211221
genericWhereClause: (genericWhereClause requirements: _* @parameter_constraints)?)?
@@ -1236,9 +1236,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12361236
// Enum class declaration: same as a regular class but with an enum body.
12371237
rule!(
12381238
(enumDecl
1239-
enumKeyword: @kind
1239+
enumKeyword: @@kind
12401240
modifiers: _* @mods
1241-
name: @name
1241+
name: @@name
12421242
genericParameterClause: (genericParameterClause
12431243
parameters: _* @params
12441244
genericWhereClause: (genericWhereClause requirements: _* @parameter_constraints)?)?
@@ -1259,9 +1259,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12591259
// A `struct` declaration.
12601260
rule!(
12611261
(structDecl
1262-
structKeyword: @kind
1262+
structKeyword: @@kind
12631263
modifiers: _* @mods
1264-
name: @name
1264+
name: @@name
12651265
genericParameterClause: (genericParameterClause
12661266
parameters: _* @params
12671267
genericWhereClause: (genericWhereClause requirements: _* @parameter_constraints)?)?
@@ -1282,9 +1282,9 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
12821282
// Protocol declaration
12831283
rule!(
12841284
(protocolDecl
1285-
protocolKeyword: @kind
1285+
protocolKeyword: @@kind
12861286
modifiers: _* @mods
1287-
name: @name
1287+
name: @@name
12881288
genericParameterClause: (genericParameterClause parameters: _* @params)?
12891289
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
12901290
genericWhereClause: (genericWhereClause requirements: _* @declaration_constraints)?
@@ -1302,7 +1302,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
13021302
// An `extension Foo.Bar { … }` is likewise a `class_like_declaration`.
13031303
rule!(
13041304
(extensionDecl
1305-
extensionKeyword: @kind
1305+
extensionKeyword: @@kind
13061306
modifiers: _* @mods
13071307
extendedType: @extendedType
13081308
inheritanceClause: (inheritanceClause inheritedTypes: (inheritedType type: @bases)*)?
@@ -1322,7 +1322,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
13221322
// nest under `signature` (as for `functionDecl`).
13231323
rule!(
13241324
(initializerDecl
1325-
initKeyword: @initK
1325+
initKeyword: @@initK
13261326
modifiers: _* @mods
13271327
signature: (functionSignature
13281328
parameterClause: (functionParameterClause parameters: _* @params))
@@ -1336,7 +1336,7 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
13361336
),
13371337
rule!(
13381338
(initializerDecl
1339-
initKeyword: @initK
1339+
initKeyword: @@initK
13401340
modifiers: _* @mods
13411341
signature: (functionSignature
13421342
parameterClause: (functionParameterClause parameters: _* @params)))
@@ -1383,18 +1383,58 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
13831383
name_node: (identifier #{name})
13841384
bound: {bound})
13851385
),
1386-
// ---- Fallbacks ----
1387-
// Bare `_` (rather than `(_)`) so this matches both named nodes
1388-
// and unnamed tokens. Any unnamed token that escapes the
1389-
// input-schema-specific rules (e.g. captured operators in
1390-
// `additive_expression op: @op`) has its auto-translated value
1391-
// replaced with an `unsupported_node` whose source range is
1392-
// inherited from the original token, so `#{op}` still reads the
1393-
// original text.
1394-
rule!(
1395-
_
1396-
=>
1397-
(unsupported_node)
1386+
// ---- Explicitly unsupported roots ----
1387+
// These kinds can reach translation independently, but we do not
1388+
// currently map them to the unified AST. Syntax nested inside one of
1389+
// these roots is discarded with its parent and needs no separate rule.
1390+
rule!((actorDecl) => (unsupported_node)),
1391+
rule!((attributedType) => (unsupported_node)),
1392+
rule!((borrowExpr) => (unsupported_node)),
1393+
rule!((classRestrictionType) => (unsupported_node)),
1394+
rule!((compositionType) => (unsupported_node)),
1395+
rule!((consumeExpr) => (unsupported_node)),
1396+
rule!((copyExpr) => (unsupported_node)),
1397+
rule!((deferStmt) => (unsupported_node)),
1398+
rule!((discardStmt) => (unsupported_node)),
1399+
rule!((fallThroughStmt) => (unsupported_node)),
1400+
rule!((ifConfigDecl) => (unsupported_node)),
1401+
rule!((implicitlyUnwrappedOptionalType) => (unsupported_node)),
1402+
rule!((inOutExpr) => (unsupported_node)),
1403+
rule!((inlineArrayType) => (unsupported_node)),
1404+
rule!((keyPathExpr) => (unsupported_node)),
1405+
rule!((macroDecl) => (unsupported_node)),
1406+
rule!((metatypeType) => (unsupported_node)),
1407+
rule!((namedOpaqueReturnType) => (unsupported_node)),
1408+
rule!((operatorDecl) => (unsupported_node)),
1409+
rule!((packElementExpr) => (unsupported_node)),
1410+
rule!((packElementType) => (unsupported_node)),
1411+
rule!((packExpansionExpr) => (unsupported_node)),
1412+
rule!((packExpansionType) => (unsupported_node)),
1413+
rule!((postfixIfConfigExpr) => (unsupported_node)),
1414+
rule!((postfixOperatorExpr) => (unsupported_node)),
1415+
rule!((poundSourceLocation) => (unsupported_node)),
1416+
rule!((precedenceGroupDecl) => (unsupported_node)),
1417+
rule!((someOrAnyType) => (unsupported_node)),
1418+
rule!((subscriptDecl) => (unsupported_node)),
1419+
rule!((suppressedType) => (unsupported_node)),
1420+
rule!((typeExpr) => (unsupported_node)),
1421+
rule!((unsafeExpr) => (unsupported_node)),
1422+
rule!((yieldStmt) => (unsupported_node)),
1423+
// Anything reaching this final generic handler has neither a
1424+
// dedicated rule nor an explicit unsupported entry.
1425+
rule!(
1426+
_ @@node
1427+
=>
1428+
unhandled_node {
1429+
let input = ctx.ast.get_node(node).expect("matched node must exist");
1430+
tracing::error!(
1431+
target: "unified_extractor",
1432+
node_kind = input.kind_name(),
1433+
source_range = ?input.source_range(),
1434+
"Unhandled Swift syntax node reached translation"
1435+
);
1436+
tree!((unhandled_node))
1437+
}
13981438
),
13991439
]
14001440
}

‎unified/ql/lib/codeql/unified/internal/Ast.qll‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,12 @@ module Unified {
14401440
}
14411441
}
14421442

1443+
/** A class representing `unhandled_node` tokens. */
1444+
class UnhandledNode extends @unified_token_unhandled_node, F::Expr, F::Member, F::Token {
1445+
/** Gets the name of the primary QL class for this element. */
1446+
final override string getAPrimaryQlClass() { result = "UnhandledNode" }
1447+
}
1448+
14431449
/** A class representing `unresolved_operator_sequence` nodes. */
14441450
class UnresolvedOperatorSequence extends @unified_unresolved_operator_sequence, F::Expr {
14451451
/** Gets the name of the primary QL class for this element. */
@@ -1976,6 +1982,8 @@ module UnifiedFinal {
19761982

19771983
final class UnaryExpr = F::UnaryExpr;
19781984

1985+
final class UnhandledNode = F::UnhandledNode;
1986+
19791987
final class UnresolvedOperatorSequence = F::UnresolvedOperatorSequence;
19801988

19811989
final class UnsupportedNode = F::UnsupportedNode;

0 commit comments

Comments
 (0)