Merge pull request #19448 from d10c/d10c/ruby-printast-order-fix

Ruby printAst: fix order for synth children of real parents
This commit is contained in:
Nora Dimitrijević
2025-05-15 18:17:01 +02:00
committed by GitHub
3 changed files with 22 additions and 10 deletions

View File

@@ -0,0 +1,6 @@
---
category: fix
---
### Bug Fixes
* The Ruby printAst.qll library now orders AST nodes slightly differently: child nodes that do not literally appear in the source code, but whose parent nodes do, are assigned a deterministic order based on a combination of source location and logical order within the parent. This fixes the non-deterministic ordering that sometimes occurred depending on evaluation order. The effect may also be visible in downstream uses of the printAst library, such as the AST view in the VSCode extension.

View File

@@ -121,17 +121,22 @@ class PrintRegularAstNode extends PrintAstNode, TPrintRegularAstNode {
} }
private int getSynthAstNodeIndex() { private int getSynthAstNodeIndex() {
this.parentIsSynthesized() and
exists(AstNode parent | exists(AstNode parent |
shouldPrintAstEdge(parent, _, astNode) and shouldPrintAstEdge(parent, _, astNode) and
parent.isSynthesized() and
synthChild(parent, result, astNode) synthChild(parent, result, astNode)
) )
or or
not this.parentIsSynthesized() and not exists(AstNode parent |
shouldPrintAstEdge(parent, _, astNode) and
synthChild(parent, _, astNode)
) and
result = 0 result = 0
} }
private int getSynthAstNodeIndexForSynthParent() {
if this.parentIsSynthesized() then result = this.getSynthAstNodeIndex() else result = 0
}
override int getOrder() { override int getOrder() {
this = this =
rank[result](PrintRegularAstNode p, Location l, File f | rank[result](PrintRegularAstNode p, Location l, File f |
@@ -140,8 +145,9 @@ class PrintRegularAstNode extends PrintAstNode, TPrintRegularAstNode {
| |
p p
order by order by
f.getBaseName(), f.getAbsolutePath(), l.getStartLine(), p.getSynthAstNodeIndex(), f.getBaseName(), f.getAbsolutePath(), l.getStartLine(),
l.getStartColumn(), l.getEndLine(), l.getEndColumn() p.getSynthAstNodeIndexForSynthParent(), l.getStartColumn(), p.getSynthAstNodeIndex(),
l.getEndLine(), l.getEndColumn()
) )
} }

View File

@@ -3185,14 +3185,14 @@ params/params.rb:
# 106| getParameter: [HashSplatParameter] **kwargs # 106| getParameter: [HashSplatParameter] **kwargs
# 106| getDefiningAccess: [LocalVariableAccess] kwargs # 106| getDefiningAccess: [LocalVariableAccess] kwargs
# 107| getStmt: [SuperCall] super call to m # 107| getStmt: [SuperCall] super call to m
# 107| getArgument: [HashSplatExpr] ** ... # 107| getArgument: [LocalVariableAccess] y
# 107| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] kwargs # 107| getArgument: [SplatExpr] * ...
# 107| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] rest
# 107| getArgument: [Pair] Pair # 107| getArgument: [Pair] Pair
# 107| getKey: [SymbolLiteral] k # 107| getKey: [SymbolLiteral] k
# 107| getValue: [LocalVariableAccess] k # 107| getValue: [LocalVariableAccess] k
# 107| getArgument: [SplatExpr] * ... # 107| getArgument: [HashSplatExpr] ** ...
# 107| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] rest # 107| getAnOperand/getOperand/getReceiver: [LocalVariableAccess] kwargs
# 107| getArgument: [LocalVariableAccess] y
# 111| getStmt: [MethodCall] call to m # 111| getStmt: [MethodCall] call to m
# 111| getReceiver: [MethodCall] call to new # 111| getReceiver: [MethodCall] call to new
# 111| getReceiver: [ConstantReadAccess] Sub # 111| getReceiver: [ConstantReadAccess] Sub