Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@ import io.joern.rust2cpg.parser.RustNodeSyntax
import io.joern.rust2cpg.parser.RustNodeSyntax.RustNode
import io.joern.x2cpg.datastructures.Stack.*
import io.joern.x2cpg.{Ast, AstCreatorBase, ValidationMode}
import io.shiftleft.codepropertygraph.generated.nodes.{
NewCall,
NewControlStructure,
NewMethod,
NewNamespaceBlock,
NewNode,
NewTypeDecl
}
import io.shiftleft.codepropertygraph.generated.nodes.{NewCall, NewMethod, NewNamespaceBlock, NewNode, NewTypeDecl}
import io.shiftleft.codepropertygraph.generated.{NodeTypes, Operators, PropertyDefaults, PropertyNames}
import io.shiftleft.semanticcpg.language.types.structure.NamespaceTraversal
import org.slf4j.LoggerFactory
Expand All @@ -29,14 +22,20 @@ class AstCreator(val config: Config, val parseResult: ParseResult)(implicit with
private val logger = LoggerFactory.getLogger(getClass)

protected val methodAstParentStack = new Stack[NewNode]
private var detachedAsts = List.empty[Ast]

override def createAst(): DiffGraphBuilder = {
val sourceFile = parseResult.ast.asInstanceOf[RustNodeSyntax.SourceFile]
val ast = visitSourceFile(sourceFile)
Ast.storeInDiffGraph(ast, diffGraph)
detachedAsts.foreach(Ast.storeInDiffGraph(_, diffGraph))
diffGraph
}

protected def addDetachedAst(ast: Ast): Unit = {
detachedAsts = ast :: detachedAsts
}

// NB: rust_ast_gen uses 0-based line/column
override protected def line(node: RustNode): Option[Int] =
if (node.isMacroExpanded) None else node.startLine.map(_ + 1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,25 +355,35 @@ trait RustVisitor(implicit withSchemaValidation: ValidationMode) { this: AstCrea
// AssocItemList
private def visitImpl(impl: Impl): Seq[Ast] = {
if (impl.forKwToken.isDefined) {
impl.typ match {
case implTrait :: implType :: Nil =>
val typeDecl = typeDeclForTraitImpl(impl, implTrait, implType)
methodAstParentStack.push(typeDecl)
val methodAsts = impl.assocItemList.assocItem.collect { case fn: Fn => visitFn(fn) }
methodAstParentStack.pop()
Ast(typeDecl).withChildren(methodAsts) :: Nil
case _ => notHandledYet(impl) :: Nil
}
lowerImplFor(impl) :: Nil
} else {
methodAstParentStack.push(typeDeclForImpl(impl))
val methodAsts = impl.assocItemList.assocItem.collect { case fn: Fn => visitFn(fn) }
methodAstParentStack.pop()
// TODO: remove this side-effect once ref-linker/scope is in.
methodAsts.foreach(Ast.storeInDiffGraph(_, diffGraph))
lowerInherentImplAsDetachedAst(impl)
Nil
}
}

// There can be at most one `impl X for Y` (for some X, Y) in the same file/project.
private def lowerImplFor(impl: Impl): Ast = {
impl.typ match {
case implTrait :: implType :: Nil =>
val typeDecl = typeDeclForTraitImpl(impl, implTrait, implType)
methodAstParentStack.push(typeDecl)
val methodAsts = impl.assocItemList.assocItem.collect { case fn: Fn => visitFn(fn) }
methodAstParentStack.pop()
Ast(typeDecl).withChildren(methodAsts)
case _ => notHandledYet(impl)
}
}

// There can be multiple `impl X` in the same file/project, so we lower their

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And their fullnames are still unique?

@xavierpinho xavierpinho Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, via typeDeclForImpl, which either takes rust_ast_gen's resolved name or builds one from the type name + current crate as a fallback. (But didn't change any logic in this PR, it's really just a refactoring.)

// methods as detached Asts. The AstLinker pass shall later create the appropriate Ast edges.
private def lowerInherentImplAsDetachedAst(impl: Impl): Unit = {
methodAstParentStack.push(typeDeclForImpl(impl))
val methodAsts = impl.assocItemList.assocItem.collect { case fn: Fn => visitFn(fn) }
methodAstParentStack.pop()
methodAsts.foreach(addDetachedAst)
}

// Trait =
// Attr* Visibility?
// 'unsafe'? 'auto'?
Expand Down
Loading