diff --git a/unified/extractor/ast_types.yml b/unified/extractor/ast_types.yml index 418772aa268..4fa1ff16942 100644 --- a/unified/extractor/ast_types.yml +++ b/unified/extractor/ast_types.yml @@ -31,6 +31,7 @@ supertypes: - throw_expr - try_expr - switch_expr + - unresolved_operator_sequence - unsupported_node expr_or_pattern: - expr @@ -38,6 +39,11 @@ supertypes: expr_or_type: - expr - type_expr + # An element of an `unresolved_operator_sequence`: either an operand (`expr`) + # or one of the infix operators separating the operands. + expr_or_operator: + - expr + - infix_operator pattern: - name_pattern - tuple_pattern @@ -137,6 +143,19 @@ named: operand: expr operator: operator + # A flat, unresolved operator sequence such as `a <+> b <+> c`. + # + # Swift's grammar doesn't encode operator precedence, so an operator chain is + # first parsed as a flat list of operands and operators. The parser front-end + # resolves this into structured `binary_expr` trees when it knows the + # operators' precedence (standard-library operators, and operators declared in + # the same file). When it encounters an operator whose precedence it can't + # determine (e.g. one imported from another module), it leaves that chain + # unresolved and emits it here rather than guessing a (possibly wrong) + # structure. The `element`s alternate operands (`expr`) and infix operators. + unresolved_operator_sequence: + element*: expr_or_operator + # Plain assignment assign_expr: target: expr_or_pattern diff --git a/unified/extractor/src/languages/mod.rs b/unified/extractor/src/languages/mod.rs index a1f5c88cf3a..032bc884ca3 100644 --- a/unified/extractor/src/languages/mod.rs +++ b/unified/extractor/src/languages/mod.rs @@ -12,6 +12,17 @@ mod swift; #[allow(dead_code)] pub mod swift_adapter; +/// Swift front-end parser: shells out to `swift-syntax-parse` and adapts its +/// JSON output via [`swift_adapter`]. +/// +/// Dormant for now: the runtime Swift front-end is still tree-sitter, so +/// nothing in the binary calls this yet. `allow(dead_code)` for the same +/// binary-crate reason as [`swift_adapter`]; both allows are removed once the +/// runtime switches the Swift front-end to swift-syntax. +#[path = "swift/parse.rs"] +#[allow(dead_code)] +pub mod swift_parse; + /// Shared YEAST output AST schema for all languages. pub(crate) const OUTPUT_AST_SCHEMA: &str = include_str!("../../ast_types.yml"); diff --git a/unified/extractor/src/languages/swift/adapter.rs b/unified/extractor/src/languages/swift/adapter.rs index 37d5aac00d2..696fce88970 100644 --- a/unified/extractor/src/languages/swift/adapter.rs +++ b/unified/extractor/src/languages/swift/adapter.rs @@ -2,9 +2,8 @@ //! in-memory format the CodeQL desugaring rules operate on. //! //! The JSON tree is produced by the `swift-syntax-rs` crate's Swift FFI shim -//! (`parse_to_json`). This module is pure Rust (only `yeast` + `serde_json`), -//! so the extractor consumes swift-syntax output without pulling in the Swift -//! toolchain (the JSON is produced out-of-process). +//! (`parse_to_json`). This module needs no Swift toolchain, so the extractor +//! consumes swift-syntax output out-of-process. //! //! The mapping mirrors tree-sitter's node model, which is what yeast (and the //! extractor's rewrite rules) expect: @@ -24,31 +23,19 @@ use std::collections::BTreeMap; +use codeql_extractor::extractor::ExtraToken; use serde_json::Value; -use yeast::schema::Schema; use yeast::{Ast, Id, NodeContent, Point, Range}; -/// A comment (or `unexpectedText`) recovered from the syntax tree's trivia. -/// -/// These are collected into a side channel rather than embedded in the -/// [`yeast::Ast`], mirroring how the extractor treats tree-sitter `extra` -/// nodes: they carry a location and text but are not attached to a parent. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct TriviaToken { - /// The trivia kind (e.g. `lineComment`, `blockComment`, `docLineComment`, - /// `docBlockComment`, `unexpectedText`). - pub kind: String, - /// The verbatim source text of the piece (e.g. `// comment`). - pub text: String, - /// The source range the piece occupies. - pub range: Range, -} - /// The result of adapting a swift-syntax JSON tree: the [`yeast::Ast`] plus the -/// comment/`unexpectedText` trivia harvested from it (in source order). +/// comment/`unexpectedText` [`ExtraToken`]s harvested from it (in source order). +/// +/// The extra tokens are collected into a side channel rather than embedded in +/// the [`yeast::Ast`], mirroring how the extractor treats tree-sitter `extra` +/// nodes: they carry a location and text but are not attached to a parent. pub struct AdaptedTree { pub ast: Ast, - pub trivia: Vec, + pub extras: Vec, } /// swift-syntax `TokenKind` cases whose text is *not* determined by the kind @@ -170,17 +157,18 @@ fn children_of(value: &Value) -> Vec<&Value> { /// in the schema on the fly, immediately before the node is created. Children /// are built first so a parent's field lists reference existing ids. Any /// comment/`unexpectedText` trivia carried by a token is harvested into -/// `trivia` during the same pass rather than embedded in the tree. -fn build(node: &Value, ast: &mut Ast, trivia: &mut Vec) -> Result { +/// `extras` (as [`ExtraToken`]s) during the same pass rather than embedded in +/// the tree. +fn build(node: &Value, ast: &mut Ast, extras: &mut Vec) -> Result { let info = classify(node)?; - collect_trivia(node, trivia); + collect_extras(node, extras); let mut fields: BTreeMap> = BTreeMap::new(); for (field, value) in field_entries(node) { let field_id = ast.register_field(field); let mut ids = Vec::new(); for child in children_of(value) { - ids.push(build(child, ast, trivia)?); + ids.push(build(child, ast, extras)?); } fields.insert(field_id, ids); } @@ -201,9 +189,10 @@ fn build(node: &Value, ast: &mut Ast, trivia: &mut Vec) -> Result) { +/// filtered to comments/`unexpectedText` upstream) into `out` as +/// [`ExtraToken`]s. Non-token nodes have no trivia keys, so this is a no-op for +/// them. +fn collect_extras(node: &Value, out: &mut Vec) { for key in ["leadingTrivia", "trailingTrivia"] { let Some(Value::Array(pieces)) = node.get(key) else { continue; @@ -220,8 +209,8 @@ fn collect_trivia(node: &Value, out: &mut Vec) { .and_then(Value::as_str) .unwrap_or("") .to_string(); - out.push(TriviaToken { - kind: kind.to_string(), + out.push(ExtraToken { + kind: trivia_kind_id(kind), text, range, }); @@ -229,6 +218,21 @@ fn collect_trivia(node: &Value, out: &mut Vec) { } } +/// Map a swift-syntax trivia kind name to the stable integer id stored in an +/// [`ExtraToken`]'s `kind` (and written to the `unified_trivia_tokeninfo` +/// table). The value is opaque to the QL library (which reads only the text), +/// but is kept stable and meaningful. +fn trivia_kind_id(kind: &str) -> usize { + match kind { + "lineComment" => 1, + "blockComment" => 2, + "docLineComment" => 3, + "docBlockComment" => 4, + "unexpectedText" => 5, + _ => 0, + } +} + /// Parse a node's `range` into a [`yeast::Range`]. /// /// The JSON carries, for `start` and `end`, a 0-based UTF-8 file byte `offset`, @@ -258,21 +262,29 @@ fn parse_range(node: &Value) -> Option { }) } +/// The authoritative swift-syntax input node-types schema, generated from +/// swift-syntax (see the schemagen tool). [`json_to_ast`] seeds every parse +/// with the schema built from this, pre-registering every input kind and field +/// so rule matching never references a name absent from a given file's tree. +const SWIFT_NODE_TYPES: &str = include_str!("../../../swift_node_types.yml"); + /// Convert a swift-syntax JSON tree (as produced by [`crate::parse_to_json`]) /// into a [`yeast::Ast`] plus the comment/`unexpectedText` trivia harvested -/// from it. Both are produced in a single traversal. +/// from it. Both are produced in a single traversal. The AST is seeded with the +/// authoritative swift-syntax schema ([`SWIFT_NODE_TYPES`]); the adapter only +/// ever consumes swift-syntax input, so the schema is not a parameter. pub fn json_to_ast(json: &str) -> Result { let root: Value = serde_json::from_str(json).map_err(|e| format!("invalid JSON: {e}"))?; - let mut ast = Ast::with_schema(Schema::new()); - let mut trivia = Vec::new(); - let root_id = build(&root, &mut ast, &mut trivia)?; + let mut ast = Ast::with_schema(yeast::node_types_yaml::schema_from_yaml(SWIFT_NODE_TYPES)?); + let mut extras = Vec::new(); + let root_id = build(&root, &mut ast, &mut extras)?; ast.set_root(root_id); - // Emit trivia in source order (the traversal visits nodes bottom-up). - trivia.sort_by_key(|t| t.range.start_byte); + // Emit extras in source order (the traversal visits nodes bottom-up). + extras.sort_by_key(|t| t.range.start_byte); - Ok(AdaptedTree { ast, trivia }) + Ok(AdaptedTree { ast, extras }) } #[cfg(test)] @@ -373,7 +385,7 @@ mod tests { } #[test] - fn collects_trivia_into_side_channel() { + fn collects_extras_into_side_channel() { // A token carrying a trailing line comment in its trivia. let json = r#"{ "kind": "sourceFile", @@ -395,9 +407,10 @@ mod tests { let adapted = json_to_ast(json).expect("adapter should succeed"); // The comment is in the side channel, with its text and location. - assert_eq!(adapted.trivia.len(), 1); - let comment = &adapted.trivia[0]; - assert_eq!(comment.kind, "lineComment"); + assert_eq!(adapted.extras.len(), 1); + let comment = &adapted.extras[0]; + // `lineComment` maps to extra kind id 1. + assert_eq!(comment.kind, 1); assert_eq!(comment.text, "// c"); assert_eq!(comment.range.start_byte, 2); assert_eq!(comment.range.end_byte, 6); diff --git a/unified/extractor/src/languages/swift/parse.rs b/unified/extractor/src/languages/swift/parse.rs new file mode 100644 index 00000000000..21ef1b9ad21 --- /dev/null +++ b/unified/extractor/src/languages/swift/parse.rs @@ -0,0 +1,73 @@ +//! Swift front-end parser: shells out to the separate `swift-syntax-parse` +//! binary (which links swift-syntax) to obtain a JSON syntax tree, then adapts +//! that JSON into a `yeast::Ast` via the pure-Rust [`swift_adapter`] module. +//! +//! Running the parser in a separate process keeps the Swift toolchain out of +//! the extractor's own build: the extractor never links Swift, so working on +//! other (e.g. tree-sitter based) languages needs no Swift toolchain. Each call +//! spawns the parser afresh; a longer-lived parser process could be swapped in +//! behind this same seam later without touching the extraction pipeline. + +use std::io::Write; +use std::process::{Command, Stdio}; + +use codeql_extractor::extractor::ParsedTree; + +use super::swift_adapter; + +/// Environment variable naming the `swift-syntax-parse` executable. When unset, +/// `swift-syntax-parse` is looked up on `PATH`. +const PARSE_BIN_ENV: &str = "CODEQL_EXTRACTOR_UNIFIED_SWIFT_SYNTAX_PARSE"; + +/// Parse Swift `source` into a [`ParsedTree`] (a raw `yeast::Ast` plus +/// side-channel `extra` tokens), ready to be desugared via `run_from_ast`. +pub fn parse(source: &[u8]) -> Result { + let source = + std::str::from_utf8(source).map_err(|e| format!("Swift source is not valid UTF-8: {e}"))?; + let json = run_parser(source)?; + let mut adapted = swift_adapter::json_to_ast(&json)?; + adapted.ast.set_source(source.as_bytes().to_vec()); + Ok(ParsedTree { + ast: adapted.ast, + extras: adapted.extras, + }) +} + +/// The `swift-syntax-parse` executable to invoke. +fn parse_bin() -> String { + std::env::var(PARSE_BIN_ENV).unwrap_or_else(|_| "swift-syntax-parse".to_string()) +} + +/// Run the external parser, feeding `source` on stdin and returning its JSON +/// stdout. +fn run_parser(source: &str) -> Result { + let bin = parse_bin(); + let mut child = Command::new(&bin) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| format!("failed to spawn Swift parser `{bin}`: {e}"))?; + + // The parser reads all of stdin before writing any stdout, so writing the + // whole source and then closing stdin (by dropping it) cannot deadlock. + child + .stdin + .take() + .expect("child stdin was piped") + .write_all(source.as_bytes()) + .map_err(|e| format!("failed to write source to Swift parser `{bin}`: {e}"))?; + + let output = child + .wait_with_output() + .map_err(|e| format!("failed to run Swift parser `{bin}`: {e}"))?; + if !output.status.success() { + return Err(format!( + "Swift parser `{bin}` failed ({}): {}", + output.status, + String::from_utf8_lossy(&output.stderr).trim() + )); + } + String::from_utf8(output.stdout) + .map_err(|e| format!("Swift parser produced non-UTF-8 output: {e}")) +} diff --git a/unified/extractor/swift_node_types.yml b/unified/extractor/swift_node_types.yml new file mode 100644 index 00000000000..d8793acce2c --- /dev/null +++ b/unified/extractor/swift_node_types.yml @@ -0,0 +1,1281 @@ +# GENERATED from swift-syntax by the one-off schemagen tool. Do not edit. +supertypes: + decl: + - accessorDecl + - actorDecl + - associatedTypeDecl + - classDecl + - deinitializerDecl + - editorPlaceholderDecl + - enumCaseDecl + - enumDecl + - extensionDecl + - functionDecl + - ifConfigDecl + - importDecl + - initializerDecl + - macroDecl + - macroExpansionDecl + - missingDecl + - operatorDecl + - poundSourceLocation + - precedenceGroupDecl + - protocolDecl + - structDecl + - subscriptDecl + - typeAliasDecl + - unexpectedCodeDecl + - usingDecl + - variableDecl + expr: + - _canImportExpr + - _canImportVersionInfo + - arrayExpr + - arrowExpr + - asExpr + - assignmentExpr + - awaitExpr + - binaryOperatorExpr + - booleanLiteralExpr + - borrowExpr + - closureExpr + - consumeExpr + - copyExpr + - declReferenceExpr + - dictionaryExpr + - discardAssignmentExpr + - doExpr + - editorPlaceholderExpr + - floatLiteralExpr + - forceUnwrapExpr + - functionCallExpr + - genericSpecializationExpr + - ifExpr + - inOutExpr + - infixOperatorExpr + - integerLiteralExpr + - isExpr + - keyPathExpr + - macroExpansionExpr + - memberAccessExpr + - missingExpr + - nilLiteralExpr + - optionalChainingExpr + - packElementExpr + - packExpansionExpr + - patternExpr + - postfixIfConfigExpr + - postfixOperatorExpr + - prefixOperatorExpr + - regexLiteralExpr + - sequenceExpr + - simpleStringLiteralExpr + - stringLiteralExpr + - subscriptCallExpr + - superExpr + - switchExpr + - ternaryExpr + - tryExpr + - tupleExpr + - typeExpr + - unresolvedAsExpr + - unresolvedIsExpr + - unresolvedTernaryExpr + - unsafeExpr + pattern: + - expressionPattern + - identifierPattern + - isTypePattern + - missingPattern + - tuplePattern + - valueBindingPattern + - wildcardPattern + stmt: + - breakStmt + - continueStmt + - deferStmt + - discardStmt + - doStmt + - expressionStmt + - fallThroughStmt + - forStmt + - guardStmt + - labeledStmt + - missingStmt + - repeatStmt + - returnStmt + - thenStmt + - throwStmt + - whileStmt + - yieldStmt + syntax: + - abiAttributeArguments + - accessorBlock + - accessorBlockFile + - accessorEffectSpecifiers + - accessorParameters + - arrayElement + - attribute + - attributeClauseFile + - availabilityArgument + - availabilityCondition + - availabilityLabeledArgument + - availabilityMacroDefinitionFile + - backDeployedAttributeArguments + - catchClause + - catchItem + - closureCapture + - closureCaptureClause + - closureCaptureSpecifier + - closureParameter + - closureParameterClause + - closureShorthandParameter + - closureSignature + - codeBlock + - codeBlockFile + - codeBlockItem + - compositionTypeElement + - conditionElement + - conformanceRequirement + - declModifier + - declModifierDetail + - declNameArgument + - declNameArguments + - deinitializerEffectSpecifiers + - derivativeAttributeArguments + - designatedType + - dictionaryElement + - differentiabilityArgument + - differentiabilityArguments + - differentiabilityWithRespectToArgument + - differentiableAttributeArguments + - documentationAttributeArgument + - dynamicReplacementAttributeArguments + - enumCaseElement + - enumCaseParameter + - enumCaseParameterClause + - expressionSegment + - functionEffectSpecifiers + - functionParameter + - functionParameterClause + - functionSignature + - genericArgument + - genericArgumentClause + - genericParameter + - genericParameterClause + - genericRequirement + - genericWhereClause + - ifConfigClause + - implementsAttributeArguments + - importPathComponent + - inheritanceClause + - inheritedType + - initializerClause + - keyPathComponent + - keyPathMethodComponent + - keyPathOptionalComponent + - keyPathPropertyComponent + - keyPathSubscriptComponent + - labeledExpr + - labeledSpecializeArgument + - layoutRequirement + - lifetimeSpecifierArgument + - lifetimeTypeSpecifier + - matchingPatternCondition + - memberBlock + - memberBlockItem + - memberBlockItemListFile + - missing + - moduleSelector + - multipleTrailingClosureElement + - nonisolatedSpecifierArgument + - nonisolatedTypeSpecifier + - objCSelectorPiece + - operatorPrecedenceAndTypes + - optionalBindingCondition + - originallyDefinedInAttributeArguments + - patternBinding + - platformVersion + - platformVersionItem + - poundSourceLocationArguments + - precedenceGroupAssignment + - precedenceGroupAssociativity + - precedenceGroupName + - precedenceGroupRelation + - primaryAssociatedType + - primaryAssociatedTypeClause + - returnClause + - sameTypeRequirement + - simpleTypeSpecifier + - sourceFile + - specializeAvailabilityArgument + - specializeTargetFunctionArgument + - specializedAttributeArgument + - stringSegment + - switchCase + - switchCaseItem + - switchCaseLabel + - switchDefaultLabel + - throwsClause + - tuplePatternElement + - tupleTypeElement + - typeAnnotation + - typeEffectSpecifiers + - typeInitializerClause + - versionComponent + - versionTuple + - whereClause + - yieldedExpression + - yieldedExpressionsClause + type: + - arrayType + - attributedType + - classRestrictionType + - compositionType + - dictionaryType + - functionType + - identifierType + - implicitlyUnwrappedOptionalType + - inlineArrayType + - memberType + - metatypeType + - missingType + - namedOpaqueReturnType + - optionalType + - packElementType + - packExpansionType + - someOrAnyType + - suppressedType + - tupleType +named: + _canImportExpr: + canImportKeyword: _token + leftParen: _token + importPath: _token + versionInfo?: _canImportVersionInfo + rightParen: _token + _canImportVersionInfo: + comma: _token + label: _token + colon: _token + version: versionTuple + abiAttributeArguments: + provider: [associatedTypeDecl, deinitializerDecl, enumCaseDecl, functionDecl, initializerDecl, missingDecl, subscriptDecl, typeAliasDecl, variableDecl] + accessorBlock: + leftBrace: _token + accessors: [accessorDecl, codeBlockItemList] + rightBrace: _token + accessorBlockFile: + leftBrace?: _token + accessors*: accessorDecl + rightBrace?: _token + endOfFileToken: _token + accessorDecl: + attributes*: [attribute, ifConfigDecl] + modifier?: declModifier + accessorSpecifier: _token + parameters?: accessorParameters + effectSpecifiers?: accessorEffectSpecifiers + body?: codeBlock + accessorEffectSpecifiers: + asyncSpecifier?: _token + throwsClause?: throwsClause + accessorParameters: + leftParen: _token + name: _token + rightParen: _token + actorDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + actorKeyword: _token + name: _token + genericParameterClause?: genericParameterClause + inheritanceClause?: inheritanceClause + genericWhereClause?: genericWhereClause + memberBlock: memberBlock + arrayElement: + expression: expr + trailingComma?: _token + arrayExpr: + leftSquare: _token + elements*: arrayElement + rightSquare: _token + arrayType: + leftSquare: _token + element: type + rightSquare: _token + arrowExpr: + effectSpecifiers?: typeEffectSpecifiers + arrow: _token + asExpr: + expression: expr + asKeyword: _token + questionOrExclamationMark?: _token + type: type + assignmentExpr: + equal: _token + associatedTypeDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + associatedtypeKeyword: _token + name: _token + inheritanceClause?: inheritanceClause + initializer?: typeInitializerClause + genericWhereClause?: genericWhereClause + attribute: + atSign: _token + attributeName: type + leftParen?: _token + arguments?: [labeledExprList, availabilityArgumentList, specializeAttributeArgumentList, specializedAttributeArgument, objCSelectorPieceList, implementsAttributeArguments, differentiableAttributeArguments, derivativeAttributeArguments, backDeployedAttributeArguments, originallyDefinedInAttributeArguments, dynamicReplacementAttributeArguments, effectsAttributeArgumentList, documentationAttributeArgumentList, abiAttributeArguments] + rightParen?: _token + attributeClauseFile: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + endOfFileToken: _token + attributedType: + specifiers*: [simpleTypeSpecifier, lifetimeTypeSpecifier, nonisolatedTypeSpecifier] + attributes*: [attribute, ifConfigDecl] + lateSpecifiers*: [simpleTypeSpecifier, lifetimeTypeSpecifier, nonisolatedTypeSpecifier] + baseType: type + availabilityArgument: + argument: [_token, platformVersion, availabilityLabeledArgument] + trailingComma?: _token + availabilityCondition: + availabilityKeyword: _token + leftParen: _token + availabilityArguments*: availabilityArgument + rightParen: _token + availabilityLabeledArgument: + label: _token + colon: _token + value: [simpleStringLiteralExpr, versionTuple] + availabilityMacroDefinitionFile: + platformVersion: platformVersion + colon: _token + specs*: availabilityArgument + endOfFileToken: _token + awaitExpr: + awaitKeyword: _token + expression: expr + backDeployedAttributeArguments: + beforeLabel: _token + colon: _token + platforms*: platformVersionItem + binaryOperatorExpr: + operator: _token + booleanLiteralExpr: + literal: _token + borrowExpr: + borrowKeyword: _token + expression: expr + breakStmt: + breakKeyword: _token + label?: _token + catchClause: + catchKeyword: _token + catchItems*: catchItem + body: codeBlock + catchItem: + pattern?: pattern + whereClause?: whereClause + trailingComma?: _token + classDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + classKeyword: _token + name: _token + genericParameterClause?: genericParameterClause + inheritanceClause?: inheritanceClause + genericWhereClause?: genericWhereClause + memberBlock: memberBlock + classRestrictionType: + classKeyword: _token + closureCapture: + specifier?: closureCaptureSpecifier + name: _token + initializer?: initializerClause + trailingComma?: _token + closureCaptureClause: + leftSquare: _token + items*: closureCapture + rightSquare: _token + closureCaptureSpecifier: + specifier: _token + leftParen?: _token + detail?: _token + rightParen?: _token + closureExpr: + leftBrace: _token + signature?: closureSignature + statements*: codeBlockItem + rightBrace: _token + closureParameter: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + firstName: _token + secondName?: _token + colon?: _token + type?: type + ellipsis?: _token + trailingComma?: _token + closureParameterClause: + leftParen: _token + parameters*: closureParameter + rightParen: _token + closureShorthandParameter: + name: _token + trailingComma?: _token + closureSignature: + attributes*: [attribute, ifConfigDecl] + capture?: closureCaptureClause + parameterClause?: [closureShorthandParameterList, closureParameterClause] + effectSpecifiers?: typeEffectSpecifiers + returnClause?: returnClause + inKeyword: _token + codeBlock: + leftBrace: _token + statements*: codeBlockItem + rightBrace: _token + codeBlockFile: + body: codeBlock + endOfFileToken: _token + codeBlockItem: + item: [decl, stmt, expr] + semicolon?: _token + compositionType: + elements*: compositionTypeElement + compositionTypeElement: + type: type + ampersand?: token + conditionElement: + condition: [expr, availabilityCondition, matchingPatternCondition, optionalBindingCondition] + trailingComma?: _token + conformanceRequirement: + leftType: type + colon: _token + rightType: type + consumeExpr: + consumeKeyword: _token + expression: expr + continueStmt: + continueKeyword: _token + label?: _token + copyExpr: + copyKeyword: _token + expression: expr + declModifier: + name: _token + detail?: declModifierDetail + declModifierDetail: + leftParen: _token + detail: _token + rightParen: _token + declNameArgument: + name: token + colon: _token + declNameArguments: + leftParen: _token + arguments*: declNameArgument + rightParen: _token + declReferenceExpr: + moduleSelector?: moduleSelector + baseName: _token + argumentNames?: declNameArguments + deferStmt: + deferKeyword: _token + body: codeBlock + deinitializerDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + deinitKeyword: _token + effectSpecifiers?: deinitializerEffectSpecifiers + body?: codeBlock + deinitializerEffectSpecifiers: + asyncSpecifier?: _token + derivativeAttributeArguments: + ofLabel: _token + colon: _token + originalDeclName: expr + period?: _token + accessorSpecifier?: _token + comma?: _token + arguments?: differentiabilityWithRespectToArgument + designatedType: + leadingComma: _token + name: token + dictionaryElement: + key: expr + colon: _token + value: expr + trailingComma?: _token + dictionaryExpr: + leftSquare: _token + content: [_token, dictionaryElementList] + rightSquare: _token + dictionaryType: + leftSquare: _token + key: type + colon: _token + value: type + rightSquare: _token + differentiabilityArgument: + argument: _token + trailingComma?: _token + differentiabilityArguments: + leftParen: _token + arguments*: differentiabilityArgument + rightParen: _token + differentiabilityWithRespectToArgument: + wrtLabel: _token + colon: _token + arguments: [differentiabilityArgument, differentiabilityArguments] + differentiableAttributeArguments: + kindSpecifier?: _token + kindSpecifierComma?: _token + arguments?: differentiabilityWithRespectToArgument + argumentsComma?: _token + genericWhereClause?: genericWhereClause + discardAssignmentExpr: + wildcard: _token + discardStmt: + discardKeyword: _token + expression: expr + doExpr: + doKeyword: _token + body: codeBlock + catchClauses*: catchClause + doStmt: + doKeyword: _token + throwsClause?: throwsClause + body: codeBlock + catchClauses*: catchClause + documentationAttributeArgument: + label: _token + colon: _token + value: [_token, stringLiteralExpr] + trailingComma?: _token + dynamicReplacementAttributeArguments: + forLabel: _token + colon: _token + declName: declReferenceExpr + editorPlaceholderDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + placeholder: _token + editorPlaceholderExpr: + placeholder: _token + enumCaseDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + caseKeyword: _token + elements*: enumCaseElement + enumCaseElement: + name: _token + parameterClause?: enumCaseParameterClause + rawValue?: initializerClause + trailingComma?: _token + enumCaseParameter: + modifiers*: declModifier + firstName?: _token + secondName?: _token + colon?: _token + type: type + defaultValue?: initializerClause + trailingComma?: _token + enumCaseParameterClause: + leftParen: _token + parameters*: enumCaseParameter + rightParen: _token + enumDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + enumKeyword: _token + name: _token + genericParameterClause?: genericParameterClause + inheritanceClause?: inheritanceClause + genericWhereClause?: genericWhereClause + memberBlock: memberBlock + expressionPattern: + expression: expr + expressionSegment: + backslash: _token + pounds?: _token + leftParen: _token + expressions*: labeledExpr + rightParen: _token + expressionStmt: + expression: expr + extensionDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + extensionKeyword: _token + extendedType: type + inheritanceClause?: inheritanceClause + genericWhereClause?: genericWhereClause + memberBlock: memberBlock + fallThroughStmt: + fallthroughKeyword: _token + floatLiteralExpr: + literal: _token + forStmt: + forKeyword: _token + tryKeyword?: _token + awaitKeyword?: _token + unsafeKeyword?: _token + caseKeyword?: _token + pattern: pattern + typeAnnotation?: typeAnnotation + inKeyword: _token + sequence: expr + whereClause?: whereClause + body: codeBlock + forceUnwrapExpr: + expression: expr + exclamationMark: _token + functionCallExpr: + calledExpression: expr + leftParen?: _token + arguments*: labeledExpr + rightParen?: _token + trailingClosure?: closureExpr + additionalTrailingClosures*: multipleTrailingClosureElement + functionDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + funcKeyword: _token + name: _token + genericParameterClause?: genericParameterClause + signature: functionSignature + genericWhereClause?: genericWhereClause + body?: codeBlock + functionEffectSpecifiers: + asyncSpecifier?: _token + throwsClause?: throwsClause + functionParameter: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + firstName: _token + secondName?: _token + colon: _token + type: type + ellipsis?: _token + defaultValue?: initializerClause + trailingComma?: _token + functionParameterClause: + leftParen: _token + parameters*: functionParameter + rightParen: _token + functionSignature: + parameterClause: functionParameterClause + effectSpecifiers?: functionEffectSpecifiers + returnClause?: returnClause + functionType: + leftParen: _token + parameters*: tupleTypeElement + rightParen: _token + effectSpecifiers?: typeEffectSpecifiers + returnClause: returnClause + genericArgument: + argument: [type, expr] + trailingComma?: _token + genericArgumentClause: + leftAngle: _token + arguments*: genericArgument + rightAngle: _token + genericParameter: + attributes*: [attribute, ifConfigDecl] + specifier?: _token + name: _token + colon?: _token + inheritedType?: type + trailingComma?: _token + genericParameterClause: + leftAngle: _token + parameters*: genericParameter + genericWhereClause?: genericWhereClause + rightAngle: _token + genericRequirement: + requirement: [sameTypeRequirement, conformanceRequirement, layoutRequirement] + trailingComma?: _token + genericSpecializationExpr: + expression: expr + genericArgumentClause: genericArgumentClause + genericWhereClause: + whereKeyword: _token + requirements*: genericRequirement + guardStmt: + guardKeyword: _token + conditions*: conditionElement + elseKeyword: _token + body: codeBlock + identifierPattern: + identifier: _token + identifierType: + moduleSelector?: moduleSelector + name: _token + genericArgumentClause?: genericArgumentClause + ifConfigClause: + poundKeyword: _token + condition?: expr + elements?: [codeBlockItemList, switchCaseList, memberBlockItemList, expr, attributeList] + ifConfigDecl: + clauses*: ifConfigClause + poundEndif: _token + ifExpr: + ifKeyword: _token + conditions*: conditionElement + body: codeBlock + elseKeyword?: _token + elseBody?: [ifExpr, codeBlock] + implementsAttributeArguments: + type: type + comma: _token + declName: declReferenceExpr + implicitlyUnwrappedOptionalType: + wrappedType: type + exclamationMark: _token + importDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + importKeyword: _token + importKindSpecifier?: _token + path*: importPathComponent + importPathComponent: + name: _token + trailingPeriod?: _token + inOutExpr: + ampersand: _token + expression: expr + infixOperatorExpr: + leftOperand: expr + operator: expr + rightOperand: expr + inheritanceClause: + colon: _token + inheritedTypes*: inheritedType + inheritedType: + type: type + trailingComma?: _token + initializerClause: + equal: _token + value: expr + initializerDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + initKeyword: _token + optionalMark?: _token + genericParameterClause?: genericParameterClause + signature: functionSignature + genericWhereClause?: genericWhereClause + body?: codeBlock + inlineArrayType: + leftSquare: _token + count: genericArgument + separator: _token + element: genericArgument + rightSquare: _token + integerLiteralExpr: + literal: _token + isExpr: + expression: expr + isKeyword: _token + type: type + isTypePattern: + isKeyword: _token + type: type + keyPathComponent: + period?: _token + component: [keyPathPropertyComponent, keyPathMethodComponent, keyPathSubscriptComponent, keyPathOptionalComponent] + keyPathExpr: + backslash: _token + root?: type + components*: keyPathComponent + keyPathMethodComponent: + declName: declReferenceExpr + leftParen: _token + arguments*: labeledExpr + rightParen: _token + keyPathOptionalComponent: + questionOrExclamationMark: _token + keyPathPropertyComponent: + declName: declReferenceExpr + genericArgumentClause?: genericArgumentClause + keyPathSubscriptComponent: + leftSquare: _token + arguments*: labeledExpr + rightSquare: _token + labeledExpr: + label?: _token + colon?: _token + expression: expr + trailingComma?: _token + labeledSpecializeArgument: + label: _token + colon: _token + value: token + trailingComma?: _token + labeledStmt: + label: _token + colon: _token + statement: stmt + layoutRequirement: + type: type + colon: _token + layoutSpecifier: _token + leftParen?: _token + size?: _token + comma?: _token + alignment?: _token + rightParen?: _token + lifetimeSpecifierArgument: + parameter: _token + trailingComma?: _token + lifetimeTypeSpecifier: + dependsOnKeyword: _token + leftParen: _token + scopedKeyword?: _token + arguments*: lifetimeSpecifierArgument + rightParen: _token + macroDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + macroKeyword: _token + name: _token + genericParameterClause?: genericParameterClause + signature: functionSignature + definition?: initializerClause + genericWhereClause?: genericWhereClause + macroExpansionDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + pound: _token + moduleSelector?: moduleSelector + macroName: _token + genericArgumentClause?: genericArgumentClause + leftParen?: _token + arguments*: labeledExpr + rightParen?: _token + trailingClosure?: closureExpr + additionalTrailingClosures*: multipleTrailingClosureElement + macroExpansionExpr: + pound: _token + moduleSelector?: moduleSelector + macroName: _token + genericArgumentClause?: genericArgumentClause + leftParen?: _token + arguments*: labeledExpr + rightParen?: _token + trailingClosure?: closureExpr + additionalTrailingClosures*: multipleTrailingClosureElement + matchingPatternCondition: + caseKeyword: _token + pattern: pattern + typeAnnotation?: typeAnnotation + initializer: initializerClause + memberAccessExpr: + base?: expr + period: _token + declName: declReferenceExpr + memberBlock: + leftBrace: _token + members*: memberBlockItem + rightBrace: _token + memberBlockItem: + decl: decl + semicolon?: _token + memberBlockItemListFile: + members*: memberBlockItem + endOfFileToken: _token + memberType: + baseType: type + period: _token + moduleSelector?: moduleSelector + name: _token + genericArgumentClause?: genericArgumentClause + metatypeType: + baseType: type + period: _token + metatypeSpecifier: _token + missing: + placeholder: _token + missingDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + placeholder: _token + missingExpr: + placeholder: _token + missingPattern: + placeholder: _token + missingStmt: + placeholder: _token + missingType: + placeholder: _token + moduleSelector: + moduleName: _token + colonColon: _token + multipleTrailingClosureElement: + label: _token + colon: _token + closure: closureExpr + namedOpaqueReturnType: + genericParameterClause: genericParameterClause + type: type + nilLiteralExpr: + nilKeyword: _token + nonisolatedSpecifierArgument: + leftParen: _token + nonsendingKeyword: _token + rightParen: _token + nonisolatedTypeSpecifier: + nonisolatedKeyword: _token + argument?: nonisolatedSpecifierArgument + objCSelectorPiece: + name?: token + colon?: _token + operatorDecl: + fixitySpecifier: _token + operatorKeyword: _token + name: _token + operatorPrecedenceAndTypes?: operatorPrecedenceAndTypes + operatorPrecedenceAndTypes: + colon: _token + precedenceGroup: _token + designatedTypes*: designatedType + optionalBindingCondition: + bindingSpecifier: _token + pattern: pattern + typeAnnotation?: typeAnnotation + initializer?: initializerClause + optionalChainingExpr: + expression: expr + questionMark: _token + optionalType: + wrappedType: type + questionMark: _token + originallyDefinedInAttributeArguments: + moduleLabel: _token + colon: _token + moduleName: stringLiteralExpr + comma: _token + platforms*: platformVersionItem + packElementExpr: + eachKeyword: _token + pack: expr + packElementType: + eachKeyword: _token + pack: type + packExpansionExpr: + repeatKeyword: _token + repetitionPattern: expr + packExpansionType: + repeatKeyword: _token + repetitionPattern: type + patternBinding: + pattern: pattern + typeAnnotation?: typeAnnotation + initializer?: initializerClause + accessorBlock?: accessorBlock + trailingComma?: _token + patternExpr: + pattern: pattern + platformVersion: + platform: _token + version?: versionTuple + platformVersionItem: + platformVersion: platformVersion + trailingComma?: _token + postfixIfConfigExpr: + base?: expr + config: ifConfigDecl + postfixOperatorExpr: + expression: expr + operator: _token + poundSourceLocation: + poundSourceLocation: _token + leftParen: _token + arguments?: poundSourceLocationArguments + rightParen: _token + poundSourceLocationArguments: + fileLabel: _token + fileColon: _token + fileName: simpleStringLiteralExpr + comma: _token + lineLabel: _token + lineColon: _token + lineNumber: _token + precedenceGroupAssignment: + assignmentLabel: _token + colon: _token + value: _token + precedenceGroupAssociativity: + associativityLabel: _token + colon: _token + value: _token + precedenceGroupDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + precedencegroupKeyword: _token + name: _token + leftBrace: _token + groupAttributes*: [precedenceGroupRelation, precedenceGroupAssignment, precedenceGroupAssociativity] + rightBrace: _token + precedenceGroupName: + name: _token + trailingComma?: _token + precedenceGroupRelation: + higherThanOrLowerThanLabel: _token + colon: _token + precedenceGroups*: precedenceGroupName + prefixOperatorExpr: + operator: _token + expression: expr + primaryAssociatedType: + name: _token + trailingComma?: _token + primaryAssociatedTypeClause: + leftAngle: _token + primaryAssociatedTypes*: primaryAssociatedType + rightAngle: _token + protocolDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + protocolKeyword: _token + name: _token + primaryAssociatedTypeClause?: primaryAssociatedTypeClause + inheritanceClause?: inheritanceClause + genericWhereClause?: genericWhereClause + memberBlock: memberBlock + regexLiteralExpr: + openingPounds?: _token + openingSlash: _token + regex: _token + closingSlash: _token + closingPounds?: _token + repeatStmt: + repeatKeyword: _token + body: codeBlock + whileKeyword: _token + condition: expr + returnClause: + arrow: _token + type: type + returnStmt: + returnKeyword: _token + expression?: expr + sameTypeRequirement: + leftType: [type, expr] + equal: _token + rightType: [type, expr] + sequenceExpr: + elements*: expr + simpleStringLiteralExpr: + openingQuote: _token + segments*: stringSegment + closingQuote: _token + simpleTypeSpecifier: + specifier: _token + someOrAnyType: + someOrAnySpecifier: _token + constraint: type + sourceFile: + shebang?: _token + statements*: codeBlockItem + endOfFileToken: _token + specializeAvailabilityArgument: + availabilityLabel: _token + colon: _token + availabilityArguments*: availabilityArgument + semicolon: _token + specializeTargetFunctionArgument: + targetLabel: _token + colon: _token + declName: declReferenceExpr + trailingComma?: _token + specializedAttributeArgument: + genericWhereClause: genericWhereClause + stringLiteralExpr: + openingPounds?: _token + openingQuote: _token + segments*: [stringSegment, expressionSegment] + closingQuote: _token + closingPounds?: _token + stringSegment: + content: _token + structDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + structKeyword: _token + name: _token + genericParameterClause?: genericParameterClause + inheritanceClause?: inheritanceClause + genericWhereClause?: genericWhereClause + memberBlock: memberBlock + subscriptCallExpr: + calledExpression: expr + leftSquare: _token + arguments*: labeledExpr + rightSquare: _token + trailingClosure?: closureExpr + additionalTrailingClosures*: multipleTrailingClosureElement + subscriptDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + subscriptKeyword: _token + genericParameterClause?: genericParameterClause + parameterClause: functionParameterClause + returnClause: returnClause + genericWhereClause?: genericWhereClause + accessorBlock?: accessorBlock + superExpr: + superKeyword: _token + suppressedType: + withoutTilde: _token + type: type + switchCase: + attribute?: attribute + label: [switchDefaultLabel, switchCaseLabel] + statements*: codeBlockItem + switchCaseItem: + pattern: pattern + whereClause?: whereClause + trailingComma?: _token + switchCaseLabel: + caseKeyword: _token + caseItems*: switchCaseItem + colon: _token + switchDefaultLabel: + defaultKeyword: _token + colon: _token + switchExpr: + switchKeyword: _token + subject: expr + leftBrace: _token + cases*: [switchCase, ifConfigDecl] + rightBrace: _token + ternaryExpr: + condition: expr + questionMark: _token + thenExpression: expr + colon: _token + elseExpression: expr + thenStmt: + thenKeyword: _token + expression: expr + throwStmt: + throwKeyword: _token + expression: expr + throwsClause: + throwsSpecifier: _token + leftParen?: _token + type?: type + rightParen?: _token + tryExpr: + tryKeyword: _token + questionOrExclamationMark?: _token + expression: expr + tupleExpr: + leftParen: _token + elements*: labeledExpr + rightParen: _token + tuplePattern: + leftParen: _token + elements*: tuplePatternElement + rightParen: _token + tuplePatternElement: + label?: _token + colon?: _token + pattern: pattern + trailingComma?: _token + tupleType: + leftParen: _token + elements*: tupleTypeElement + rightParen: _token + tupleTypeElement: + inoutKeyword?: _token + firstName?: _token + secondName?: _token + colon?: _token + type: type + ellipsis?: _token + trailingComma?: _token + typeAliasDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + typealiasKeyword: _token + name: _token + genericParameterClause?: genericParameterClause + initializer: typeInitializerClause + genericWhereClause?: genericWhereClause + typeAnnotation: + colon: _token + type: type + typeEffectSpecifiers: + asyncSpecifier?: _token + throwsClause?: throwsClause + typeExpr: + type: type + typeInitializerClause: + equal: _token + value: type + unexpectedCodeDecl: + unresolvedAsExpr: + asKeyword: _token + questionOrExclamationMark?: _token + unresolvedIsExpr: + isKeyword: _token + unresolvedTernaryExpr: + questionMark: _token + thenExpression: expr + colon: _token + unsafeExpr: + unsafeKeyword: _token + expression: expr + usingDecl: + usingKeyword: _token + specifier: [attribute, _token] + valueBindingPattern: + bindingSpecifier: _token + pattern: pattern + variableDecl: + attributes*: [attribute, ifConfigDecl] + modifiers*: declModifier + bindingSpecifier: _token + bindings*: patternBinding + versionComponent: + period: _token + number: _token + versionTuple: + major: _token + components*: versionComponent + whereClause: + whereKeyword: _token + condition: expr + whileStmt: + whileKeyword: _token + conditions*: conditionElement + body: codeBlock + wildcardPattern: + wildcard: _token + yieldStmt: + yieldKeyword: _token + yieldedExpressions: [yieldedExpressionsClause, expr] + yieldedExpression: + expression: expr + comma?: _token + yieldedExpressionsClause: + leftParen: _token + elements*: yieldedExpression + rightParen: _token + _token: + binaryOperator: + dollarIdentifier: + floatLiteral: + identifier: + integerLiteral: + postfixOperator: + prefixOperator: + rawStringPoundDelimiter: + regexLiteralPattern: + regexPoundDelimiter: + shebang: + unknown: diff --git a/unified/ql/lib/codeql/unified/Ast.qll b/unified/ql/lib/codeql/unified/Ast.qll index 8adb4c2e44a..e9a827269cc 100644 --- a/unified/ql/lib/codeql/unified/Ast.qll +++ b/unified/ql/lib/codeql/unified/Ast.qll @@ -567,6 +567,8 @@ module Unified { final override AstNode getAFieldOrChild() { unified_expr_equality_pattern_def(this, result) } } + final class ExprOrOperator extends @unified_expr_or_operator, AstNodeImpl { } + final class ExprOrPattern extends @unified_expr_or_pattern, AstNodeImpl { } final class ExprOrType extends @unified_expr_or_type, AstNodeImpl { } @@ -1407,6 +1409,22 @@ module Unified { } } + /** A class representing `unresolved_operator_sequence` nodes. */ + final class UnresolvedOperatorSequence extends @unified_unresolved_operator_sequence, AstNodeImpl { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "UnresolvedOperatorSequence" } + + /** Gets the node corresponding to the field `element`. */ + final ExprOrOperator getElement(int i) { + unified_unresolved_operator_sequence_element(this, i, result) + } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_unresolved_operator_sequence_element(this, _, result) + } + } + /** A class representing `unsupported_node` tokens. */ final class UnsupportedNode extends @unified_token_unsupported_node, TokenImpl { /** Gets the name of the primary QL class for this element. */ @@ -1773,6 +1791,8 @@ module Unified { or result = node.(UnaryExpr).getOperator() and i = -1 and name = "getOperator" or + result = node.(UnresolvedOperatorSequence).getElement(i) and name = "getElement" + or result = node.(VariableDeclaration).getModifier(i) and name = "getModifier" or result = node.(VariableDeclaration).getPattern() and i = -1 and name = "getPattern" diff --git a/unified/ql/lib/unified.dbscheme b/unified/ql/lib/unified.dbscheme index e957e303c22..3aafb2a494f 100644 --- a/unified/ql/lib/unified.dbscheme +++ b/unified/ql/lib/unified.dbscheme @@ -452,13 +452,15 @@ unified_equality_type_constraint_def( int right: @unified_type_expr ref ); -@unified_expr = @unified_array_literal | @unified_assign_expr | @unified_binary_expr | @unified_block | @unified_break_expr | @unified_call_expr | @unified_compound_assign_expr | @unified_continue_expr | @unified_function_expr | @unified_if_expr | @unified_key_value_pair | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_expr | @unified_throw_expr | @unified_token_boolean_literal | @unified_token_builtin_expr | @unified_token_empty_expr | @unified_token_float_literal | @unified_token_int_literal | @unified_token_regex_literal | @unified_token_string_literal | @unified_token_super_expr | @unified_token_unsupported_node | @unified_try_expr | @unified_tuple_expr | @unified_type_cast_expr | @unified_type_test_expr | @unified_unary_expr +@unified_expr = @unified_array_literal | @unified_assign_expr | @unified_binary_expr | @unified_block | @unified_break_expr | @unified_call_expr | @unified_compound_assign_expr | @unified_continue_expr | @unified_function_expr | @unified_if_expr | @unified_key_value_pair | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_expr | @unified_throw_expr | @unified_token_boolean_literal | @unified_token_builtin_expr | @unified_token_empty_expr | @unified_token_float_literal | @unified_token_int_literal | @unified_token_regex_literal | @unified_token_string_literal | @unified_token_super_expr | @unified_token_unsupported_node | @unified_try_expr | @unified_tuple_expr | @unified_type_cast_expr | @unified_type_test_expr | @unified_unary_expr | @unified_unresolved_operator_sequence unified_expr_equality_pattern_def( unique int id: @unified_expr_equality_pattern, int expr: @unified_expr ref ); +@unified_expr_or_operator = @unified_expr | @unified_token_infix_operator + @unified_expr_or_pattern = @unified_expr | @unified_pattern @unified_expr_or_type = @unified_expr | @unified_type_expr @@ -999,6 +1001,17 @@ unified_unary_expr_def( int operator: @unified_operator ref ); +#keyset[unified_unresolved_operator_sequence, index] +unified_unresolved_operator_sequence_element( + int unified_unresolved_operator_sequence: @unified_unresolved_operator_sequence ref, + int index: int ref, + unique int element: @unified_expr_or_operator ref +); + +unified_unresolved_operator_sequence_def( + unique int id: @unified_unresolved_operator_sequence +); + #keyset[unified_variable_declaration, index] unified_variable_declaration_modifier( int unified_variable_declaration: @unified_variable_declaration ref, @@ -1072,7 +1085,7 @@ unified_trivia_tokeninfo( string value: string ref ); -@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_variable_declaration | @unified_while_stmt +@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_unresolved_operator_sequence | @unified_variable_declaration | @unified_while_stmt unified_ast_node_location( unique int node: @unified_ast_node ref,