Skip to content

Commit

Permalink
added new conditions for classes, functions, checks for attributes, m…
Browse files Browse the repository at this point in the history
…oved fillUseList
  • Loading branch information
Hidanio committed Apr 18, 2024
1 parent e2120c3 commit 2e08a06
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 46 deletions.
72 changes: 65 additions & 7 deletions src/linter/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,6 @@ func (b *blockWalker) EnterNode(n ir.Node) (res bool) {

if b.isIndexingComplete() {
b.linter.enterNode(n)

list := b.linter.useList
println(list)
}
if b.isIndexingComplete() {
// Note: no need to check localRset for nil.
Expand All @@ -509,10 +506,7 @@ func (b *blockWalker) EnterNode(n ir.Node) (res bool) {
if !res {
b.path.Pop()
}
// false is an output and does not occur very often, the last values will be false
if res == false {
b.r.useList = b.linter.useList
}

return res
}

Expand Down Expand Up @@ -558,7 +552,71 @@ func (b *blockWalker) handleAndCheckGlobalStmt(s *ir.GlobalStmt) {
}
}

func (b *blockWalker) checkFunParamsAttribute(fun *ir.FunctionStmt) {
if cap(fun.Params) == 0 {
return
}

for _, item := range fun.Params {
param, _ := item.(*ir.Parameter)
if attrGroups := param.AttrGroups; attrGroups != nil {
for _, group := range attrGroups {
if group.Attrs == nil {
continue
}

for _, attribute := range group.Attrs {
name := attribute.Name.(*ir.Name)

for _, use := range b.r.useList {
useName := use.pointer.Use.Value
var alias = ""
if use.pointer.Alias != nil {
alias = use.pointer.Alias.Value
}

if strings.Contains(useName, name.Value) || (alias != "" && strings.Contains(alias, name.Value)) {
b.r.useList["\\"+useName] = UsePair{true, b.r.useList["\\"+useName].pointer}
}
}
}
}
}
}
}

func (b *blockWalker) checkFunAttribute(fun *ir.FunctionStmt) {
if fun.AttrGroups == nil {
return
}

for _, group := range fun.AttrGroups {
if group.Attrs == nil {
continue
}

for _, attribute := range group.Attrs {
name := attribute.Name.(*ir.Name)

for _, use := range b.r.useList {
useName := use.pointer.Use.Value
var alias = ""
if use.pointer.Alias != nil {
alias = use.pointer.Alias.Value
}

if strings.Contains(useName, name.Value) || (alias != "" && strings.Contains(alias, name.Value)) {
b.r.useList["\\"+useName] = UsePair{true, b.r.useList["\\"+useName].pointer}
}
}
}
}
}

func (b *blockWalker) handleFunction(fun *ir.FunctionStmt) bool {
b.checkFunParamsAttribute(fun)
b.checkFunAttribute(fun)

if b.ignoreFunctionBodies {
return false
}
Expand Down
75 changes: 36 additions & 39 deletions src/linter/block_linter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,6 @@ import (
type blockLinter struct {
walker *blockWalker
quickfix *QuickFixGenerator
useList map[string]UsePair
}

type UsePair struct {
isUsed bool
pointer *ir.UseStmt
}

func (b *blockLinter) fillUseList(uses []ir.Node) {
for _, use := range uses {
stm, ok := use.(*ir.UseStmt)
if !ok {
return
}

if b.useList == nil {
b.useList = make(map[string]UsePair)
}
key := "\\" + stm.Use.Value
b.useList[key] = UsePair{false, stm}
}
}

func (b *blockLinter) enterNode(n ir.Node) {
Expand All @@ -54,9 +33,6 @@ func (b *blockLinter) enterNode(n ir.Node) {
case *ir.ClassStmt:
b.checkClass(n)

case *ir.UseListStmt:
b.fillUseList(n.Uses)

case *ir.FunctionCallExpr:
b.checkFunctionCall(n)

Expand Down Expand Up @@ -235,10 +211,10 @@ func (b *blockLinter) checkClass(class *ir.ClassStmt) {
const classMethod = 0
const classOtherMember = 1

if b.useList != nil {
if b.walker.r.useList != nil {
doc, found := irutil.FindPHPDoc(class, true)
if found {
for _, use := range b.useList {
for _, use := range b.walker.r.useList {
useName := use.pointer.Use.Value
var index = strings.LastIndex(useName, "\\")
var alias = ""
Expand All @@ -248,7 +224,7 @@ func (b *blockLinter) checkClass(class *ir.ClassStmt) {

var phpDocFindUse = "@mixin " + useName[index+1:]
if strings.Contains(doc, phpDocFindUse) || (alias != "" && strings.Contains(doc, "@mixin "+alias)) {
b.useList["\\"+useName] = UsePair{true, b.useList["\\"+useName].pointer}
b.walker.r.useList["\\"+useName] = UsePair{true, b.walker.r.useList["\\"+useName].pointer}
}
}
}
Expand Down Expand Up @@ -544,9 +520,9 @@ func (b *blockLinter) checkNew(e *ir.NewExpr) {
className = b.classParseState().Namespace + className
args = anon.Args

var isUseStm = b.useList[className]
var isUseStm = b.walker.r.useList[className]
if isUseStm.pointer != nil {
b.useList[className] = UsePair{true, b.useList[className].pointer}
b.walker.r.useList[className] = UsePair{true, b.walker.r.useList[className].pointer}
}
} else {
className, ok = solver.GetClassName(b.classParseState(), e.Class)
Expand All @@ -557,8 +533,18 @@ func (b *blockLinter) checkNew(e *ir.NewExpr) {
args = e.Args
}

if b.useList[className].pointer != nil {
b.useList[className] = UsePair{true, b.useList[className].pointer}
if b.walker.r.useList[className].pointer != nil {
b.walker.r.useList[className] = UsePair{true, b.walker.r.useList[className].pointer}
} else {
parts := strings.Split(className, "\\")
lastPart := parts[len(parts)-1]
leftPart := strings.Join(parts[:len(parts)-1], "\\")

if b.walker.r.useList[lastPart].pointer != nil {
b.walker.r.useList[lastPart] = UsePair{true, b.walker.r.useList[lastPart].pointer}
} else if leftPart != "" && b.walker.r.useList[leftPart].pointer != nil {
b.walker.r.useList[leftPart] = UsePair{true, b.walker.r.useList[leftPart].pointer}
}
}

class, ok := b.metaInfo().GetClass(className)
Expand Down Expand Up @@ -1057,14 +1043,8 @@ func (b *blockLinter) checkFunctionCall(e *ir.FunctionCallExpr) {
call := resolveFunctionCall(b.walker.ctx.sc, b.classParseState(), b.walker.ctx.customTypes, e)
fqName := call.funcName

/* if pair, ok := b.useList[fqName]; ok && pair.pointer != nil {
pair.isUsed = true
b.useList[fqName] = pair
}
*/
if b.useList[fqName].pointer != nil {
//b.useList[fqName].isUsed = true
b.useList[fqName] = UsePair{true, b.useList[fqName].pointer}
if b.walker.r.useList[fqName].pointer != nil {
b.walker.r.useList[fqName] = UsePair{true, b.walker.r.useList[fqName].pointer}
}

if call.isClosure {
Expand Down Expand Up @@ -1336,6 +1316,23 @@ func (b *blockLinter) checkStaticCall(e *ir.StaticCallExpr) {
return
}

class, ok := e.Class.(*ir.Name)
if ok {
className := class.Value

for _, use := range b.walker.r.useList {
useName := use.pointer.Use.Value
var alias = ""

if use.pointer.Alias != nil {
alias = use.pointer.Alias.Value
}
if strings.Contains(useName, className) || (alias != "" && strings.Contains(alias, className)) {
b.walker.r.useList["\\"+useName] = UsePair{true, b.walker.r.useList["\\"+useName].pointer}
}
}
}

call := resolveStaticMethodCall(b.walker.ctx.sc, b.classParseState(), e)
if !call.canAnalyze {
return
Expand Down
23 changes: 23 additions & 0 deletions src/linter/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,26 @@ type rootWalker struct {
checker *rootChecker
}

type UsePair struct {
isUsed bool
pointer *ir.UseStmt
}

func (d *rootWalker) fillUseList(uses []ir.Node) {
for _, use := range uses {
stm, ok := use.(*ir.UseStmt)
if !ok {
return
}

if d.useList == nil {
d.useList = make(map[string]UsePair)
}
key := "\\" + stm.Use.Value
d.useList[key] = UsePair{false, stm}
}
}

// InitCustom is needed to initialize walker state
func (d *rootWalker) InitCustom() {
d.custom = nil
Expand Down Expand Up @@ -149,6 +169,9 @@ func (d *rootWalker) EnterNode(n ir.Node) (res bool) {
}
}

case *ir.UseListStmt:
d.fillUseList(n.Uses)

case *ir.AnonClassExpr:
d.currentClassNodeStack.Push(n)

Expand Down

0 comments on commit 2e08a06

Please sign in to comment.