Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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 @@ -245,6 +245,7 @@ class AstCreator(
logger.debug(
s"Trait use statement encountered. This is not yet supported. Location: $relativeFileName:${line(stmt)}"
)

Ast(unknownNode(stmt, code(stmt)))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,12 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
dynamicStmts: List[PhpStmt],
staticStmts: List[PhpStmt]
): Ast = {
val inheritsFrom = (stmt.extendsNames ++ stmt.implementedInterfaces).map(_.name)
val useTraitNames = dynamicStmts.collect { case x: PhpTraitUseStmt => x }.flatMap(_.traits)
val inheritsFrom = (stmt.extendsNames ++ useTraitNames ++ stmt.implementedInterfaces).map(_.name)
val inheritsFromMeta =
(stmt.extendsNames ++ stmt.implementedInterfaces).map(name => s"${name.name}$MetaTypeDeclExtension")
(stmt.extendsNames ++ useTraitNames ++ stmt.implementedInterfaces).map(name =>
s"${name.name}$MetaTypeDeclExtension"
)

val className = stmt.name match {
case Some(name) => name.name
Expand Down Expand Up @@ -218,9 +221,27 @@ trait AstForTypesCreator(implicit withSchemaValidation: ValidationMode) { this:
dynamicStmts: List[PhpStmt],
staticStmts: List[PhpStmt]
): List[Ast] = {
val inheritsFrom = (stmt.extendsNames ++ stmt.implementedInterfaces).map(_.name)
/*
the `use <trait>` can be used anywhere in a class definition, but the method is available to be called in any function in the class so we find all the traits before processing the rest of the class.
In the below sample, if we execute `(Foo.new())->foo()` it executes the `traitFunc` even though the `use <trait>` is after the `foo` method
```php
trait TraitA {
function traitFunc() {}
}
class Foo {
function foo() {
$this->traitFunc();
}
use TraitA;
}
```
*/
val useTraitNames = dynamicStmts.collect { case x: PhpTraitUseStmt => x }.flatMap(_.traits)
val inheritsFrom = (stmt.extendsNames ++ useTraitNames ++ stmt.implementedInterfaces).map(_.name)
val inheritsFromMeta =
(stmt.extendsNames ++ stmt.implementedInterfaces).map(name => s"${name.name}$MetaTypeDeclExtension")
(stmt.extendsNames ++ useTraitNames ++ stmt.implementedInterfaces).map(name =>
s"${name.name}$MetaTypeDeclExtension"
)
val code = codeForClassStmt(stmt, name)

val (dedupedName, fullName) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,16 @@ class TypeNodeTests extends PhpCode2CpgFixture {
val cpg = code("""<?php
|interface Foo {}
|class Bar {}
|class Baz extends Bar implements Foo {}
|trait TraitA {}
|trait TraitB {}
|class Baz extends Bar implements Foo {
| use TraitA, TraitB;
|}
|""".stripMargin)

"have baseTypeDecl for dynamic TYPE_DECL" in {
cpg.typeDecl.name("Baz").baseTypeDecl.l.map(_.name) shouldBe List("Bar", "Foo")
cpg.typeDecl.name("Baz").baseTypeDeclTransitive.l.map(_.name) shouldBe List("Bar", "Foo")
cpg.typeDecl.name("Baz").baseTypeDecl.l.map(_.name) shouldBe List("Bar", "TraitA", "TraitB", "Foo")
cpg.typeDecl.name("Baz").baseTypeDeclTransitive.l.map(_.name) shouldBe List("Bar", "TraitA", "TraitB", "Foo")
}

"have baseTypeDecl steps for meta TYPE_DECL (<metaclass>)" in {
Expand Down
Loading